diff --git a/0001-userpref-GnuTLS-Fix-3.6.0-SHA1-compatibility.patch b/0001-userpref-GnuTLS-Fix-3.6.0-SHA1-compatibility.patch deleted file mode 100644 index 5404438..0000000 --- a/0001-userpref-GnuTLS-Fix-3.6.0-SHA1-compatibility.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 0994996671d98b67d576ebe4a7b1314a61411066 Mon Sep 17 00:00:00 2001 -From: Bastien Nocera -Date: Fri, 15 Sep 2017 16:00:09 +0200 -Subject: [PATCH 1/2] userpref: [GnuTLS] Fix 3.6.0 SHA1 compatibility - -Verification will fail if a special flag is not passed. Use -gnutls_x509_crt_sign2() instead of gnutls_x509_crt_sign() to make -sure that passing this flag works in 3.6.0 and stays working with -3.6.1. ---- - common/userpref.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/common/userpref.c b/common/userpref.c -index 3ae503a..f496fee 100644 ---- a/common/userpref.c -+++ b/common/userpref.c -@@ -603,7 +603,7 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da - gnutls_x509_crt_set_ca_status(root_cert, 1); - gnutls_x509_crt_set_activation_time(root_cert, time(NULL)); - gnutls_x509_crt_set_expiration_time(root_cert, time(NULL) + (60 * 60 * 24 * 365 * 10)); -- gnutls_x509_crt_sign(root_cert, root_cert, root_privkey); -+ gnutls_x509_crt_sign2(root_cert, root_cert, root_privkey, GNUTLS_DIG_SHA1, 0); - - gnutls_x509_crt_set_key(host_cert, host_privkey); - gnutls_x509_crt_set_serial(host_cert, "\x00", 1); -@@ -612,7 +612,7 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da - gnutls_x509_crt_set_key_usage(host_cert, GNUTLS_KEY_KEY_ENCIPHERMENT | GNUTLS_KEY_DIGITAL_SIGNATURE); - gnutls_x509_crt_set_activation_time(host_cert, time(NULL)); - gnutls_x509_crt_set_expiration_time(host_cert, time(NULL) + (60 * 60 * 24 * 365 * 10)); -- gnutls_x509_crt_sign(host_cert, root_cert, root_privkey); -+ gnutls_x509_crt_sign2(host_cert, root_cert, root_privkey, GNUTLS_DIG_SHA1, 0); - - /* export to PEM format */ - size_t root_key_export_size = 0; -@@ -720,7 +720,7 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da - } - - gnutls_x509_crt_set_key_usage(dev_cert, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT); -- gnutls_error = gnutls_x509_crt_sign(dev_cert, root_cert, root_privkey); -+ gnutls_error = gnutls_x509_crt_sign2(dev_cert, root_cert, root_privkey, GNUTLS_DIG_SHA1, 0); - if (GNUTLS_E_SUCCESS == gnutls_error) { - /* if everything went well, export in PEM format */ - size_t export_size = 0; --- -2.14.1 - diff --git a/0002-userpref-GnuTLS-Use-valid-serial-for-3.6.0.patch b/0002-userpref-GnuTLS-Use-valid-serial-for-3.6.0.patch deleted file mode 100644 index f89c2bd..0000000 --- a/0002-userpref-GnuTLS-Use-valid-serial-for-3.6.0.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 3c1ca82ba31945de4e673525afb4774189011ce4 Mon Sep 17 00:00:00 2001 -From: Bastien Nocera -Date: Fri, 15 Sep 2017 16:02:42 +0200 -Subject: [PATCH 2/2] userpref: [GnuTLS] Use valid serial for >= 3.6.0 - -Another change in 3.6.0 is that a serial of '\0' is not valid anymore. -Bump it to one. ---- - common/userpref.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/common/userpref.c b/common/userpref.c -index f496fee..be745cb 100644 ---- a/common/userpref.c -+++ b/common/userpref.c -@@ -598,7 +598,7 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da - - /* generate certificates */ - gnutls_x509_crt_set_key(root_cert, root_privkey); -- gnutls_x509_crt_set_serial(root_cert, "\x00", 1); -+ gnutls_x509_crt_set_serial(root_cert, "\x01", 1); - gnutls_x509_crt_set_version(root_cert, 3); - gnutls_x509_crt_set_ca_status(root_cert, 1); - gnutls_x509_crt_set_activation_time(root_cert, time(NULL)); -@@ -606,7 +606,7 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da - gnutls_x509_crt_sign2(root_cert, root_cert, root_privkey, GNUTLS_DIG_SHA1, 0); - - gnutls_x509_crt_set_key(host_cert, host_privkey); -- gnutls_x509_crt_set_serial(host_cert, "\x00", 1); -+ gnutls_x509_crt_set_serial(host_cert, "\x01", 1); - gnutls_x509_crt_set_version(host_cert, 3); - gnutls_x509_crt_set_ca_status(host_cert, 0); - gnutls_x509_crt_set_key_usage(host_cert, GNUTLS_KEY_KEY_ENCIPHERMENT | GNUTLS_KEY_DIGITAL_SIGNATURE); -@@ -703,7 +703,7 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da - if (GNUTLS_E_SUCCESS == gnutls_error) { - /* now generate device certificate */ - gnutls_x509_crt_set_key(dev_cert, fake_privkey); -- gnutls_x509_crt_set_serial(dev_cert, "\x00", 1); -+ gnutls_x509_crt_set_serial(dev_cert, "\x01", 1); - gnutls_x509_crt_set_version(dev_cert, 3); - gnutls_x509_crt_set_ca_status(dev_cert, 0); - gnutls_x509_crt_set_activation_time(dev_cert, time(NULL)); --- -2.14.1 - diff --git a/344409e1d1ad917d377b256214c5411dda82e6b0...5a85432719fb3d18027d528f87d2a44b76fd3e12.patch b/344409e1d1ad917d377b256214c5411dda82e6b0...5a85432719fb3d18027d528f87d2a44b76fd3e12.patch deleted file mode 100644 index 05d4640..0000000 --- a/344409e1d1ad917d377b256214c5411dda82e6b0...5a85432719fb3d18027d528f87d2a44b76fd3e12.patch +++ /dev/null @@ -1,5313 +0,0 @@ -From 1ff3448d2e27f1bac8d2f0af8b8e952854860278 Mon Sep 17 00:00:00 2001 -From: Martin Szulecki -Date: Thu, 29 Jan 2015 22:21:27 +0100 -Subject: [PATCH 01/65] m4: Use python-config if available to fix Python 3 - support on newer distros - ---- - m4/ac_python_devel.m4 | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/m4/ac_python_devel.m4 b/m4/ac_python_devel.m4 -index 2e7406e..545c607 100644 ---- a/m4/ac_python_devel.m4 -+++ b/m4/ac_python_devel.m4 -@@ -151,6 +151,9 @@ $ac_distutils_result]) - # Check for Python include path - # - AC_MSG_CHECKING([for Python include path]) -+ if type $PYTHON-config; then -+ PYTHON_CPPFLAGS=`$PYTHON-config --includes` -+ fi - if test -z "$PYTHON_CPPFLAGS"; then - python_path=`$PYTHON -c "import distutils.sysconfig; \ - print(distutils.sysconfig.get_python_inc());"` -@@ -166,6 +169,9 @@ $ac_distutils_result]) - # Check for Python library path - # - AC_MSG_CHECKING([for Python library path]) -+ if type $PYTHON-config; then -+ PYTHON_LDFLAGS=`$PYTHON-config --ldflags` -+ fi - if test -z "$PYTHON_LDFLAGS"; then - # (makes two attempts to ensure we've got a version number - # from the interpreter) --- -2.14.1 - - -From 65def891530879ffe9b45c1ccee64a6bed1ea93f Mon Sep 17 00:00:00 2001 -From: Nikias Bassen -Date: Sun, 24 May 2015 00:12:48 +0200 -Subject: [PATCH 02/65] lockdown: Remove unneeded plist_free() calls since - entire dict is freed later - ---- - src/lockdown.c | 5 ----- - 1 file changed, 5 deletions(-) - -diff --git a/src/lockdown.c b/src/lockdown.c -index d1296c9..7cb3091 100644 ---- a/src/lockdown.c -+++ b/src/lockdown.c -@@ -960,8 +960,6 @@ static lockdownd_error_t lockdownd_do_pair(lockdownd_client_t client, lockdownd_ - if (extra_node && plist_get_node_type(extra_node) == PLIST_DATA) { - debug_info("Saving EscrowBag from response in pair record"); - plist_dict_set_item(pair_record_plist, USERPREF_ESCROW_BAG_KEY, plist_copy(extra_node)); -- plist_free(extra_node); -- extra_node = NULL; - } - - /* save previously retrieved wifi mac address in pair record */ -@@ -991,9 +989,6 @@ static lockdownd_error_t lockdownd_do_pair(lockdownd_client_t client, lockdownd_ - ret = lockdownd_strtoerr(value); - free(value); - } -- -- plist_free(error_node); -- error_node = NULL; - } - } - --- -2.14.1 - - -From e1cac25e632955da0c3aeb2f16f49c5a1687f81c Mon Sep 17 00:00:00 2001 -From: Nikias Bassen -Date: Fri, 10 Jul 2015 03:03:23 +0200 -Subject: [PATCH 03/65] lockdown: Add more error codes - ---- - cython/lockdown.pxi | 8 ++++++++ - include/libimobiledevice/lockdown.h | 4 ++++ - src/lockdown.c | 10 +++++++++- - 3 files changed, 21 insertions(+), 1 deletion(-) - -diff --git a/cython/lockdown.pxi b/cython/lockdown.pxi -index 7d903d6..c8d511e 100644 ---- a/cython/lockdown.pxi -+++ b/cython/lockdown.pxi -@@ -38,6 +38,10 @@ cdef extern from "libimobiledevice/lockdown.h": - LOCKDOWN_E_MISSING_ACTIVATION_RECORD - LOCKDOWN_E_SERVICE_PROHIBITED - LOCKDOWN_E_ESCROW_LOCKED -+ LOCKDOWN_E_PAIRING_PROHIBITED_OVER_THIS_CONNECTION -+ LOCKDOWN_E_FMIP_PROTECTED -+ LOCKDOWN_E_MC_PROTECTED -+ LOCKDOWN_E_MC_CHALLENGE_REQUIRED - LOCKDOWN_E_UNKNOWN_ERROR - - lockdownd_error_t lockdownd_client_new(idevice_t device, lockdownd_client_t *client, char *label) -@@ -103,6 +107,10 @@ cdef class LockdownError(BaseError): - LOCKDOWN_E_MISSING_ACTIVATION_RECORD: "Missing activation record", - LOCKDOWN_E_SERVICE_PROHIBITED: "Service prohibited", - LOCKDOWN_E_ESCROW_LOCKED: "Escrow locked", -+ LOCKDOWN_E_PAIRING_PROHIBITED_OVER_THIS_CONNECTION: "Pairing prohibited over this connection", -+ LOCKDOWN_E_FMIP_PROTECTED: "Find My iPhone/iPod/iPad protected", -+ LOCKDOWN_E_MC_PROTECTED: "MC protected", -+ LOCKDOWN_E_MC_CHALLENGE_REQUIRED: "MC challenge required", - LOCKDOWN_E_UNKNOWN_ERROR: "Unknown error" - } - BaseError.__init__(self, *args, **kwargs) -diff --git a/include/libimobiledevice/lockdown.h b/include/libimobiledevice/lockdown.h -index 076fa9d..46792a6 100644 ---- a/include/libimobiledevice/lockdown.h -+++ b/include/libimobiledevice/lockdown.h -@@ -73,6 +73,10 @@ typedef enum { - LOCKDOWN_E_MISSING_ACTIVATION_RECORD = -33, - LOCKDOWN_E_SERVICE_PROHIBITED = -34, - LOCKDOWN_E_ESCROW_LOCKED = -35, -+ LOCKDOWN_E_PAIRING_PROHIBITED_OVER_THIS_CONNECTION = -36, -+ LOCKDOWN_E_FMIP_PROTECTED = -37, -+ LOCKDOWN_E_MC_PROTECTED = -38, -+ LOCKDOWN_E_MC_CHALLENGE_REQUIRED = -39, - LOCKDOWN_E_UNKNOWN_ERROR = -256 - } lockdownd_error_t; - -diff --git a/src/lockdown.c b/src/lockdown.c -index 7cb3091..026d1d1 100644 ---- a/src/lockdown.c -+++ b/src/lockdown.c -@@ -3,7 +3,7 @@ - * com.apple.mobile.lockdownd service implementation. - * - * Copyright (c) 2009-2015 Martin Szulecki All Rights Reserved. -- * Copyright (c) 2014 Nikias Bassen. All Rights Reserved. -+ * Copyright (c) 2014-2015 Nikias Bassen All Rights Reserved. - * Copyright (c) 2010 Bryan Forbes All Rights Reserved. - * Copyright (c) 2008 Zach C. All Rights Reserved. - * -@@ -122,6 +122,14 @@ static lockdownd_error_t lockdownd_strtoerr(const char* name) - err = LOCKDOWN_E_SERVICE_PROHIBITED; - } else if (strcmp(name, "EscrowLocked") == 0) { - err = LOCKDOWN_E_ESCROW_LOCKED; -+ } else if (strcmp(name, "PairingProhibitedOverThisConnection") == 0) { -+ err = LOCKDOWN_E_PAIRING_PROHIBITED_OVER_THIS_CONNECTION; -+ } else if (strcmp(name, "FMiPProtected") == 0) { -+ err = LOCKDOWN_E_FMIP_PROTECTED; -+ } else if (strcmp(name, "MCProtected") == 0) { -+ err = LOCKDOWN_E_MC_PROTECTED; -+ } else if (strcmp(name, "MCChallengeRequired") == 0) { -+ err = LOCKDOWN_E_MC_CHALLENGE_REQUIRED; - } - - return err; --- -2.14.1 - - -From f268393d4e447ac901879bee751d7350c495fed2 Mon Sep 17 00:00:00 2001 -From: Nikias Bassen -Date: Wed, 15 Jul 2015 07:22:37 +0200 -Subject: [PATCH 04/65] lockdown: Add new lockdownd_pair_with_options() - function - ---- - include/libimobiledevice/lockdown.h | 19 +++++++++++++++++++ - src/lockdown.c | 37 ++++++++++++++++++++++++++++--------- - 2 files changed, 47 insertions(+), 9 deletions(-) - -diff --git a/include/libimobiledevice/lockdown.h b/include/libimobiledevice/lockdown.h -index 46792a6..0e48eef 100644 ---- a/include/libimobiledevice/lockdown.h -+++ b/include/libimobiledevice/lockdown.h -@@ -295,6 +295,25 @@ lockdownd_error_t lockdownd_receive(lockdownd_client_t client, plist_t *plist); - */ - lockdownd_error_t lockdownd_pair(lockdownd_client_t client, lockdownd_pair_record_t pair_record); - -+ /** -+ * Pairs the device using the supplied pair record and passing the given options. -+ * -+ * @param client The lockdown client -+ * @param pair_record The pair record to use for pairing. If NULL is passed, then -+ * the pair records from the current machine are used. New records will be -+ * generated automatically when pairing is done for the first time. -+ * @param options The pairing options to pass. Can be NULL for no options. -+ * @param response If non-NULL a pointer to lockdownd's response dictionary is returned. -+ * The caller is responsible to free the response dictionary with plist_free(). -+ * -+ * @return LOCKDOWN_E_SUCCESS on success, LOCKDOWN_E_INVALID_ARG when client is NULL, -+ * LOCKDOWN_E_PLIST_ERROR if the pair_record certificates are wrong, -+ * LOCKDOWN_E_PAIRING_FAILED if the pairing failed, -+ * LOCKDOWN_E_PASSWORD_PROTECTED if the device is password protected, -+ * LOCKDOWN_E_INVALID_HOST_ID if the device does not know the caller's host id -+ */ -+lockdownd_error_t lockdownd_pair_with_options(lockdownd_client_t client, lockdownd_pair_record_t pair_record, plist_t options, plist_t *response); -+ - /** - * Validates if the device is paired with the given HostID. If successful the - * specified host will become trusted host of the device indicated by the -diff --git a/src/lockdown.c b/src/lockdown.c -index 026d1d1..85124bd 100644 ---- a/src/lockdown.c -+++ b/src/lockdown.c -@@ -848,6 +848,8 @@ leave: - * the pair records from the current machine are used. New records will be - * generated automatically when pairing is done for the first time. - * @param verb This is either "Pair", "ValidatePair" or "Unpair". -+ * @param options The pairing options to pass. -+ * @param response If non-NULL a pointer to lockdownd's response dictionary is returned. - * - * @return LOCKDOWN_E_SUCCESS on success, NP_E_INVALID_ARG when client is NULL, - * LOCKDOWN_E_PLIST_ERROR if the pair_record certificates are wrong, -@@ -855,7 +857,7 @@ leave: - * LOCKDOWN_E_PASSWORD_PROTECTED if the device is password protected, - * LOCKDOWN_E_INVALID_HOST_ID if the device does not know the caller's host id - */ --static lockdownd_error_t lockdownd_do_pair(lockdownd_client_t client, lockdownd_pair_record_t pair_record, const char *verb) -+static lockdownd_error_t lockdownd_do_pair(lockdownd_client_t client, lockdownd_pair_record_t pair_record, const char *verb, plist_t options, plist_t *result) - { - if (!client) - return LOCKDOWN_E_INVALID_ARG; -@@ -915,9 +917,9 @@ static lockdownd_error_t lockdownd_do_pair(lockdownd_client_t client, lockdownd_ - plist_dict_set_item(dict, "Request", plist_new_string(verb)); - plist_dict_set_item(dict, "ProtocolVersion", plist_new_string(LOCKDOWN_PROTOCOL_VERSION)); - -- plist_t options = plist_new_dict(); -- plist_dict_set_item(options, "ExtendedPairingErrors", plist_new_bool(1)); -- plist_dict_set_item(dict, "PairingOptions", options); -+ if (options) { -+ plist_dict_set_item(dict, "PairingOptions", plist_copy(options)); -+ } - - /* send to device */ - ret = lockdownd_send(client, dict); -@@ -1010,25 +1012,42 @@ static lockdownd_error_t lockdownd_do_pair(lockdownd_client_t client, lockdownd_ - wifi_node = NULL; - } - -- plist_free(dict); -- dict = NULL; -+ if (result) { -+ *result = dict; -+ } else { -+ plist_free(dict); -+ dict = NULL; -+ } - - return ret; - } - - LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_pair(lockdownd_client_t client, lockdownd_pair_record_t pair_record) - { -- return lockdownd_do_pair(client, pair_record, "Pair"); -+ -+ plist_t options = plist_new_dict(); -+ plist_dict_set_item(options, "ExtendedPairingErrors", plist_new_bool(1)); -+ -+ lockdownd_error_t ret = lockdownd_do_pair(client, pair_record, "Pair", options, NULL); -+ -+ plist_free(options); -+ -+ return ret; -+} -+ -+LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_pair_with_options(lockdownd_client_t client, lockdownd_pair_record_t pair_record, plist_t options, plist_t *response) -+{ -+ return lockdownd_do_pair(client, pair_record, "Pair", options, response); - } - - LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_validate_pair(lockdownd_client_t client, lockdownd_pair_record_t pair_record) - { -- return lockdownd_do_pair(client, pair_record, "ValidatePair"); -+ return lockdownd_do_pair(client, pair_record, "ValidatePair", NULL, NULL); - } - - LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_unpair(lockdownd_client_t client, lockdownd_pair_record_t pair_record) - { -- return lockdownd_do_pair(client, pair_record, "Unpair"); -+ return lockdownd_do_pair(client, pair_record, "Unpair", NULL, NULL); - } - - LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_enter_recovery(lockdownd_client_t client) --- -2.14.1 - - -From 2d5c2195bbdcc02774fa3f70a23759b3cb8b4aed Mon Sep 17 00:00:00 2001 -From: Martin Szulecki -Date: Tue, 6 Oct 2015 22:07:56 +0200 -Subject: [PATCH 05/65] Add missing "(void)" to functions to match public - headers - ---- - src/idevice.c | 2 +- - src/installation_proxy.c | 2 +- - src/mobilesync.c | 2 +- - 3 files changed, 3 insertions(+), 3 deletions(-) - -diff --git a/src/idevice.c b/src/idevice.c -index ce27495..7c33cdd 100644 ---- a/src/idevice.c -+++ b/src/idevice.c -@@ -168,7 +168,7 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_event_subscribe(idevice_event_cb_t - return IDEVICE_E_SUCCESS; - } - --LIBIMOBILEDEVICE_API idevice_error_t idevice_event_unsubscribe() -+LIBIMOBILEDEVICE_API idevice_error_t idevice_event_unsubscribe(void) - { - event_cb = NULL; - int res = usbmuxd_unsubscribe(); -diff --git a/src/installation_proxy.c b/src/installation_proxy.c -index e858e58..8bde154 100644 ---- a/src/installation_proxy.c -+++ b/src/installation_proxy.c -@@ -914,7 +914,7 @@ LIBIMOBILEDEVICE_API void instproxy_command_get_name(plist_t command, char** nam - } - } - --LIBIMOBILEDEVICE_API plist_t instproxy_client_options_new() -+LIBIMOBILEDEVICE_API plist_t instproxy_client_options_new(void) - { - return plist_new_dict(); - } -diff --git a/src/mobilesync.c b/src/mobilesync.c -index 06fb1c1..d903cfe 100644 ---- a/src/mobilesync.c -+++ b/src/mobilesync.c -@@ -739,7 +739,7 @@ LIBIMOBILEDEVICE_API void mobilesync_anchors_free(mobilesync_anchors_t anchors) - anchors = NULL; - } - --LIBIMOBILEDEVICE_API plist_t mobilesync_actions_new() -+LIBIMOBILEDEVICE_API plist_t mobilesync_actions_new(void) - { - return plist_new_dict(); - } --- -2.14.1 - - -From d93043e6243e691a17135b221dd9275c10f8edbc Mon Sep 17 00:00:00 2001 -From: Martin Szulecki -Date: Tue, 6 Oct 2015 22:10:56 +0200 -Subject: [PATCH 06/65] tools: Use PACKAGE_URL define for homepage project - links in usage output - ---- - tools/idevice_id.c | 6 +++++- - tools/idevicebackup.c | 2 +- - tools/idevicebackup2.c | 6 +++++- - tools/idevicecrashreport.c | 6 +++++- - tools/idevicedate.c | 6 +++++- - tools/idevicedebug.c | 6 +++++- - tools/idevicedebugserverproxy.c | 6 +++++- - tools/idevicediagnostics.c | 6 +++++- - tools/ideviceenterrecovery.c | 6 +++++- - tools/ideviceimagemounter.c | 6 +++++- - tools/ideviceinfo.c | 6 +++++- - tools/idevicename.c | 6 +++++- - tools/idevicenotificationproxy.c | 6 +++++- - tools/idevicepair.c | 6 +++++- - tools/ideviceprovision.c | 7 ++++++- - tools/idevicescreenshot.c | 6 +++++- - tools/idevicesyslog.c | 6 +++++- - 17 files changed, 82 insertions(+), 17 deletions(-) - -diff --git a/tools/idevice_id.c b/tools/idevice_id.c -index 9629f8b..6f020ff 100644 ---- a/tools/idevice_id.c -+++ b/tools/idevice_id.c -@@ -19,6 +19,10 @@ - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -+#ifdef HAVE_CONFIG_H -+#include -+#endif -+ - #include - #include - #include -@@ -42,7 +46,7 @@ static void print_usage(int argc, char **argv) - printf(" -d, --debug\t\tenable communication debugging\n"); - printf(" -h, --help\t\tprints usage information\n"); - printf("\n"); -- printf("Homepage: \n"); -+ printf("Homepage: <" PACKAGE_URL ">\n"); - } - - int main(int argc, char **argv) -diff --git a/tools/idevicebackup.c b/tools/idevicebackup.c -index eefaa6f..2619cc9 100644 ---- a/tools/idevicebackup.c -+++ b/tools/idevicebackup.c -@@ -674,7 +674,7 @@ static void print_usage(int argc, char **argv) - printf(" -u, --udid UDID\ttarget specific device by its 40-digit device UDID\n"); - printf(" -h, --help\t\tprints usage information\n"); - printf("\n"); -- printf("Homepage: \n"); -+ printf("Homepage: <" PACKAGE_URL ">\n"); - } - - int main(int argc, char *argv[]) -diff --git a/tools/idevicebackup2.c b/tools/idevicebackup2.c -index ead4dba..934cf39 100644 ---- a/tools/idevicebackup2.c -+++ b/tools/idevicebackup2.c -@@ -20,6 +20,10 @@ - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -+#ifdef HAVE_CONFIG_H -+#include -+#endif -+ - #include - #include - #include -@@ -1139,7 +1143,7 @@ static void print_usage(int argc, char **argv) - printf(" -i, --interactive\trequest passwords interactively\n"); - printf(" -h, --help\t\tprints usage information\n"); - printf("\n"); -- printf("Homepage: \n"); -+ printf("Homepage: <" PACKAGE_URL ">\n"); - } - - int main(int argc, char *argv[]) -diff --git a/tools/idevicecrashreport.c b/tools/idevicecrashreport.c -index b74a660..7ac9baf 100644 ---- a/tools/idevicecrashreport.c -+++ b/tools/idevicecrashreport.c -@@ -20,6 +20,10 @@ - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -+#ifdef HAVE_CONFIG_H -+#include -+#endif -+ - #include - #include - #include -@@ -298,7 +302,7 @@ static void print_usage(int argc, char **argv) - printf(" -u, --udid UDID\ttarget specific device by its 40-digit device UDID\n"); - printf(" -h, --help\t\tprints usage information\n"); - printf("\n"); -- printf("Homepage: \n"); -+ printf("Homepage: <" PACKAGE_URL ">\n"); - } - - int main(int argc, char* argv[]) { -diff --git a/tools/idevicedate.c b/tools/idevicedate.c -index f6bed7a..97243bb 100644 ---- a/tools/idevicedate.c -+++ b/tools/idevicedate.c -@@ -19,6 +19,10 @@ - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -+#ifdef HAVE_CONFIG_H -+#include -+#endif -+ - #include - #include - #include -@@ -51,7 +55,7 @@ static void print_usage(int argc, char **argv) - printf(" -c, --sync\t\tset time of device to current system time\n"); - printf(" -h, --help\t\tprints usage information\n"); - printf("\n"); -- printf("Homepage: \n"); -+ printf("Homepage: <" PACKAGE_URL ">\n"); - } - - int main(int argc, char *argv[]) -diff --git a/tools/idevicedebug.c b/tools/idevicedebug.c -index 6a30ec4..b00893d 100644 ---- a/tools/idevicedebug.c -+++ b/tools/idevicedebug.c -@@ -19,6 +19,10 @@ - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -+#ifdef HAVE_CONFIG_H -+#include -+#endif -+ - #include - #include - #include -@@ -188,7 +192,7 @@ static void print_usage(int argc, char **argv) - printf(" -d, --debug\t\tenable communication debugging\n"); - printf(" -h, --help\t\tprints usage information\n"); - printf("\n"); -- printf("Homepage: \n"); -+ printf("Homepage: <" PACKAGE_URL ">\n"); - } - - int main(int argc, char *argv[]) -diff --git a/tools/idevicedebugserverproxy.c b/tools/idevicedebugserverproxy.c -index 28bba5e..f270cdc 100644 ---- a/tools/idevicedebugserverproxy.c -+++ b/tools/idevicedebugserverproxy.c -@@ -19,6 +19,10 @@ - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -+#ifdef HAVE_CONFIG_H -+#include -+#endif -+ - #include - #include - #include -@@ -70,7 +74,7 @@ static void print_usage(int argc, char **argv) - printf(" -u, --udid UDID\ttarget specific device by its 40-digit device UDID\n"); - printf(" -h, --help\t\tprints usage information\n"); - printf("\n"); -- printf("Homepage: \n"); -+ printf("Homepage: <" PACKAGE_URL ">\n"); - } - - static void *thread_device_to_client(void *data) -diff --git a/tools/idevicediagnostics.c b/tools/idevicediagnostics.c -index 992bc0a..8b6569d 100644 ---- a/tools/idevicediagnostics.c -+++ b/tools/idevicediagnostics.c -@@ -19,6 +19,10 @@ - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -+#ifdef HAVE_CONFIG_H -+#include -+#endif -+ - #include - #include - #include -@@ -296,5 +300,5 @@ void print_usage(int argc, char **argv) - printf(" -u, --udid UDID\ttarget specific device by its 40-digit device UDID\n"); - printf(" -h, --help\t\tprints usage information\n"); - printf("\n"); -- printf("Homepage: \n"); -+ printf("Homepage: <" PACKAGE_URL ">\n"); - } -diff --git a/tools/ideviceenterrecovery.c b/tools/ideviceenterrecovery.c -index 3069be8..21c4ff6 100644 ---- a/tools/ideviceenterrecovery.c -+++ b/tools/ideviceenterrecovery.c -@@ -19,6 +19,10 @@ - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -+#ifdef HAVE_CONFIG_H -+#include -+#endif -+ - #include - #include - #include -@@ -37,7 +41,7 @@ static void print_usage(int argc, char **argv) - printf(" -d, --debug\t\tenable communication debugging\n"); - printf(" -h, --help\t\tprints usage information\n"); - printf("\n"); -- printf("Homepage: \n"); -+ printf("Homepage: <" PACKAGE_URL ">\n"); - } - - int main(int argc, char *argv[]) -diff --git a/tools/ideviceimagemounter.c b/tools/ideviceimagemounter.c -index a0f4b83..ad3222a 100644 ---- a/tools/ideviceimagemounter.c -+++ b/tools/ideviceimagemounter.c -@@ -19,6 +19,10 @@ - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -+#ifdef HAVE_CONFIG_H -+#include -+#endif -+ - #include - #define _GNU_SOURCE 1 - #define __USE_GNU 1 -@@ -66,7 +70,7 @@ static void print_usage(int argc, char **argv) - printf(" -d, --debug\t\tenable communication debugging\n"); - printf(" -h, --help\t\tprints usage information\n"); - printf("\n"); -- printf("Homepage: \n"); -+ printf("Homepage: <" PACKAGE_URL ">\n"); - } - - static void parse_opts(int argc, char **argv) -diff --git a/tools/ideviceinfo.c b/tools/ideviceinfo.c -index 641a036..40bcac6 100644 ---- a/tools/ideviceinfo.c -+++ b/tools/ideviceinfo.c -@@ -19,6 +19,10 @@ - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -+#ifdef HAVE_CONFIG_H -+#include -+#endif -+ - #include - #include - #include -@@ -98,7 +102,7 @@ static void print_usage(int argc, char **argv) - printf(" %s\n", domains[i++]); - } - printf("\n"); -- printf("Homepage: \n"); -+ printf("Homepage: <" PACKAGE_URL ">\n"); - } - - int main(int argc, char *argv[]) -diff --git a/tools/idevicename.c b/tools/idevicename.c -index b5b9e62..013becc 100644 ---- a/tools/idevicename.c -+++ b/tools/idevicename.c -@@ -19,6 +19,10 @@ - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -+#ifdef HAVE_CONFIG_H -+#include -+#endif -+ - #include - #include - #include -@@ -37,7 +41,7 @@ static void print_usage(void) - printf(" -u, --udid UDID\tuse UDID to target a specific device\n"); - printf(" -h, --help\t\tprint usage information\n"); - printf("\n"); -- printf("Homepage: \n"); -+ printf("Homepage: <" PACKAGE_URL ">\n"); - } - - int main(int argc, char** argv) -diff --git a/tools/idevicenotificationproxy.c b/tools/idevicenotificationproxy.c -index ff18eca..5e4ac9a 100644 ---- a/tools/idevicenotificationproxy.c -+++ b/tools/idevicenotificationproxy.c -@@ -19,6 +19,10 @@ - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -+#ifdef HAVE_CONFIG_H -+#include -+#endif -+ - #include - #include - #include -@@ -69,7 +73,7 @@ static void print_usage(int argc, char **argv) - printf(" -u, --udid UDID\ttarget specific device by its 40-digit device UDID\n"); - printf(" -h, --help\t\tprints usage information\n"); - printf("\n"); -- printf("Homepage: \n"); -+ printf("Homepage: <" PACKAGE_URL ">\n"); - } - - static void notify_cb(const char *notification, void *user_data) -diff --git a/tools/idevicepair.c b/tools/idevicepair.c -index 237b168..f34369e 100644 ---- a/tools/idevicepair.c -+++ b/tools/idevicepair.c -@@ -20,6 +20,10 @@ - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -+#ifdef HAVE_CONFIG_H -+#include -+#endif -+ - #include - #include - #include -@@ -71,7 +75,7 @@ static void print_usage(int argc, char **argv) - printf(" -u, --udid UDID target specific device by its 40-digit device UDID\n"); - printf(" -h, --help prints usage information\n"); - printf("\n"); -- printf("Homepage: \n"); -+ printf("Homepage: <" PACKAGE_URL ">\n"); - } - - static void parse_opts(int argc, char **argv) -diff --git a/tools/ideviceprovision.c b/tools/ideviceprovision.c -index 9517af8..4915c05 100644 ---- a/tools/ideviceprovision.c -+++ b/tools/ideviceprovision.c -@@ -19,6 +19,11 @@ - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -+ -+#ifdef HAVE_CONFIG_H -+#include -+#endif -+ - #include - #include - #include -@@ -57,7 +62,7 @@ static void print_usage(int argc, char **argv) - printf(" -x, --xml print XML output when using the 'dump' command\n"); - printf(" -h, --help prints usage information\n"); - printf("\n"); -- printf("Homepage: \n"); -+ printf("Homepage: <" PACKAGE_URL ">\n"); - } - - enum { -diff --git a/tools/idevicescreenshot.c b/tools/idevicescreenshot.c -index bff502c..da229e2 100644 ---- a/tools/idevicescreenshot.c -+++ b/tools/idevicescreenshot.c -@@ -19,6 +19,10 @@ - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -+#ifdef HAVE_CONFIG_H -+#include -+#endif -+ - #include - #include - #include -@@ -147,5 +151,5 @@ void print_usage(int argc, char **argv) - printf(" -u, --udid UDID\ttarget specific device by its 40-digit device UDID\n"); - printf(" -h, --help\t\tprints usage information\n"); - printf("\n"); -- printf("Homepage: \n"); -+ printf("Homepage: <" PACKAGE_URL ">\n"); - } -diff --git a/tools/idevicesyslog.c b/tools/idevicesyslog.c -index 4bc4b45..47d2f8c 100644 ---- a/tools/idevicesyslog.c -+++ b/tools/idevicesyslog.c -@@ -19,6 +19,10 @@ - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -+#ifdef HAVE_CONFIG_H -+#include "config.h" -+#endif -+ - #include - #include - #include -@@ -206,6 +210,6 @@ void print_usage(int argc, char **argv) - printf(" -u, --udid UDID\ttarget specific device by its 40-digit device UDID\n"); - printf(" -h, --help\t\tprints usage information\n"); - printf("\n"); -- printf("Homepage: \n"); -+ printf("Homepage: <" PACKAGE_URL ">\n"); - } - --- -2.14.1 - - -From 40f7dd06496d5b1c8963f760a10a217df926cd85 Mon Sep 17 00:00:00 2001 -From: Nikias Bassen -Date: Fri, 9 Oct 2015 15:43:22 +0200 -Subject: [PATCH 07/65] common: Add missing gnutls/openssl CFLAGS to - Makefile.am - ---- - common/Makefile.am | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/common/Makefile.am b/common/Makefile.am -index a79094b..054e2a1 100644 ---- a/common/Makefile.am -+++ b/common/Makefile.am -@@ -1,6 +1,6 @@ - AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir) - --AM_CFLAGS = $(GLOBAL_CFLAGS) $(libusbmuxd_CFLAGS) $(libplist_CFLAGS) $(LFS_CFLAGS) -+AM_CFLAGS = $(GLOBAL_CFLAGS) $(libusbmuxd_CFLAGS) $(libplist_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(openssl_CFLAGS) $(LFS_CFLAGS) - AM_LDFLAGS = $(libusbmuxd_LIBS) $(libplist_LIBS) ${libpthread_LIBS} - - noinst_LTLIBRARIES = libinternalcommon.la --- -2.14.1 - - -From 6070126868069f2ee01ea9414f4cfbe5de285267 Mon Sep 17 00:00:00 2001 -From: "Jay Freeman (saurik)" -Date: Wed, 21 Oct 2015 00:39:14 -0700 -Subject: [PATCH 08/65] Fix installation_proxy when using GnuTLS instead of - OpenSSL - ---- - src/idevice.c | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -diff --git a/src/idevice.c b/src/idevice.c -index 7c33cdd..b776e84 100644 ---- a/src/idevice.c -+++ b/src/idevice.c -@@ -393,10 +393,13 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_receive_timeout(idevice_ - } - - if (connection->ssl_data) { --#ifdef HAVE_OPENSSL - uint32_t received = 0; - while (received < len) { -+#ifdef HAVE_OPENSSL - int r = SSL_read(connection->ssl_data->session, (void*)((char*)(data+received)), (int)len-received); -+#else -+ ssize_t r = gnutls_record_recv(connection->ssl_data->session, (void*)(data+received), (size_t)len-received); -+#endif - if (r > 0) { - received += r; - } else { -@@ -404,9 +407,6 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_receive_timeout(idevice_ - } - } - debug_info("SSL_read %d, received %d", len, received); --#else -- ssize_t received = gnutls_record_recv(connection->ssl_data->session, (void*)data, (size_t)len); --#endif - if (received > 0) { - *recv_bytes = received; - return IDEVICE_E_SUCCESS; --- -2.14.1 - - -From 2203f4cba9ddaacee1ad702b7948da0e59d33497 Mon Sep 17 00:00:00 2001 -From: Nikias Bassen -Date: Fri, 18 Dec 2015 20:46:46 +0100 -Subject: [PATCH 09/65] tools: Fix inverted abort condition in - idevicecrashreport - -This bug caused it to never wait for the 'ping' message from -the crashreportmover service ---- - tools/idevicecrashreport.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/tools/idevicecrashreport.c b/tools/idevicecrashreport.c -index 7ac9baf..8c04fd1 100644 ---- a/tools/idevicecrashreport.c -+++ b/tools/idevicecrashreport.c -@@ -405,7 +405,7 @@ int main(int argc, char* argv[]) { - /* read "ping" message which indicates the crash logs have been moved to a safe harbor */ - char *ping = malloc(4); - int attempts = 0; -- while ((strncmp(ping, "ping", 4) != 0) && (attempts > 10)) { -+ while ((strncmp(ping, "ping", 4) != 0) && (attempts < 10)) { - uint32_t bytes = 0; - device_error = idevice_connection_receive_timeout(connection, ping, 4, &bytes, 2000); - if ((bytes == 0) && (device_error == IDEVICE_E_SUCCESS)) { --- -2.14.1 - - -From cae19fa6cf28074b51ce421d64142f7ec1e1dde2 Mon Sep 17 00:00:00 2001 -From: Nikias Bassen -Date: Fri, 18 Dec 2015 21:01:01 +0100 -Subject: [PATCH 10/65] tools: idevicecrashreport: Propertly initialize buffer - used to check for ping message - ---- - tools/idevicecrashreport.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/tools/idevicecrashreport.c b/tools/idevicecrashreport.c -index 8c04fd1..8502938 100644 ---- a/tools/idevicecrashreport.c -+++ b/tools/idevicecrashreport.c -@@ -404,6 +404,7 @@ int main(int argc, char* argv[]) { - - /* read "ping" message which indicates the crash logs have been moved to a safe harbor */ - char *ping = malloc(4); -+ memset(ping, '\0', 4); - int attempts = 0; - while ((strncmp(ping, "ping", 4) != 0) && (attempts < 10)) { - uint32_t bytes = 0; --- -2.14.1 - - -From decffad5f5a0320b1b6e9e8cda821534ba2ed0ca Mon Sep 17 00:00:00 2001 -From: Nikias Bassen -Date: Tue, 22 Dec 2015 18:10:35 +0100 -Subject: [PATCH 11/65] tools: idevicecrashreport: Fix missing 0-term when - creating local filename - -When a .synced file is encountered, the .synced should be stripped off the -local filename. However the strncpy doesn't 0-terminate the string by itself -so the output filename usually contains some garbage characters at the end. -This commit properly 0-terminates the local filename to avoid this. ---- - tools/idevicecrashreport.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/tools/idevicecrashreport.c b/tools/idevicecrashreport.c -index 8502938..4d7f41c 100644 ---- a/tools/idevicecrashreport.c -+++ b/tools/idevicecrashreport.c -@@ -144,7 +144,9 @@ static int afc_client_copy_and_remove_crash_reports(afc_client_t afc, const char - char* p = strrchr(list[k], '.'); - if (p != NULL && !strncmp(p, ".synced", 7)) { - /* make sure to strip ".synced" extension as seen on iOS 5 */ -- strncpy(((char*)target_filename) + host_directory_length, list[k], strlen(list[k]) - 7); -+ int newlen = strlen(list[k]) - 7; -+ strncpy(((char*)target_filename) + host_directory_length, list[k], newlen); -+ target_filename[host_directory_length + newlen] = '\0'; - } else { - strcpy(((char*)target_filename) + host_directory_length, list[k]); - } --- -2.14.1 - - -From df1f5c4d70d0c19ad40072f5246ca457e7f9849e Mon Sep 17 00:00:00 2001 -From: Joshua Hill -Date: Tue, 29 Dec 2015 22:27:17 +0100 -Subject: [PATCH 12/65] common: [security fix] Make sure sockets only listen - locally - ---- - common/socket.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/common/socket.c b/common/socket.c -index b276864..e2968a6 100644 ---- a/common/socket.c -+++ b/common/socket.c -@@ -172,7 +172,7 @@ int socket_create(uint16_t port) - - memset((void *) &saddr, 0, sizeof(saddr)); - saddr.sin_family = AF_INET; -- saddr.sin_addr.s_addr = htonl(INADDR_ANY); -+ saddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - saddr.sin_port = htons(port); - - if (0 > bind(sfd, (struct sockaddr *) &saddr, sizeof(saddr))) { -@@ -329,7 +329,7 @@ int socket_accept(int fd, uint16_t port) - - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; -- addr.sin_addr.s_addr = htonl(INADDR_ANY); -+ addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - addr.sin_port = htons(port); - - addr_len = sizeof(addr); --- -2.14.1 - - -From 35b0543ec2a54250be011a9ffdd1d70f2c1ced5c Mon Sep 17 00:00:00 2001 -From: BALATON Zoltan -Date: Wed, 23 Sep 2015 02:11:54 +0200 -Subject: [PATCH 13/65] idevicebackup: fix some timestamps that are relative to - the Mac epoch instead of Unix one - ---- - common/utils.h | 2 ++ - tools/idevicebackup.c | 4 ++-- - tools/idevicebackup2.c | 7 ++++--- - 3 files changed, 8 insertions(+), 5 deletions(-) - -diff --git a/common/utils.h b/common/utils.h -index 90cfa4a..8426bc0 100644 ---- a/common/utils.h -+++ b/common/utils.h -@@ -33,6 +33,8 @@ - #include - #include - -+#define MAC_EPOCH 978307200 -+ - #ifndef HAVE_STPCPY - char *stpcpy(char *s1, const char *s2); - #endif -diff --git a/tools/idevicebackup.c b/tools/idevicebackup.c -index 2619cc9..7e825de 100644 ---- a/tools/idevicebackup.c -+++ b/tools/idevicebackup.c -@@ -251,7 +251,7 @@ static plist_t mobilebackup_factory_info_plist_new(const char* udid) - if (value_node) - plist_dict_set_item(ret, "IMEI", plist_copy(value_node)); - -- plist_dict_set_item(ret, "Last Backup Date", plist_new_date(time(NULL), 0)); -+ plist_dict_set_item(ret, "Last Backup Date", plist_new_date(time(NULL) - MAC_EPOCH, 0)); - - value_node = plist_dict_get_item(root_node, "ProductType"); - plist_dict_set_item(ret, "Product Type", plist_copy(value_node)); -@@ -288,7 +288,7 @@ static void mobilebackup_info_update_last_backup_date(plist_t info_plist) - return; - - node = plist_dict_get_item(info_plist, "Last Backup Date"); -- plist_set_date_val(node, time(NULL), 0); -+ plist_set_date_val(node, time(NULL) - MAC_EPOCH, 0); - - node = NULL; - } -diff --git a/tools/idevicebackup2.c b/tools/idevicebackup2.c -index 934cf39..be5a1a0 100644 ---- a/tools/idevicebackup2.c -+++ b/tools/idevicebackup2.c -@@ -146,10 +146,10 @@ static void mobilebackup_afc_get_file_contents(afc_client_t afc, const char *fil - uint32_t bread = 0; - afc_file_read(afc, f, buf+done, 65536, &bread); - if (bread > 0) { -+ done += bread; - } else { - break; - } -- done += bread; - } - if (done == fsize) { - *size = fsize; -@@ -223,7 +223,7 @@ static plist_t mobilebackup_factory_info_plist_new(const char* udid, lockdownd_c - if (value_node) - plist_dict_set_item(ret, "IMEI", plist_copy(value_node)); - -- plist_dict_set_item(ret, "Last Backup Date", plist_new_date(time(NULL), 0)); -+ plist_dict_set_item(ret, "Last Backup Date", plist_new_date(time(NULL) - MAC_EPOCH, 0)); - - value_node = plist_dict_get_item(root_node, "PhoneNumber"); - if (value_node && (plist_get_node_type(value_node) == PLIST_STRING)) { -@@ -914,7 +914,8 @@ static void mb2_handle_list_directory(mobilebackup2_client_t mobilebackup2, plis - } - plist_dict_set_item(fdict, "DLFileType", plist_new_string(ftype)); - plist_dict_set_item(fdict, "DLFileSize", plist_new_uint(st.st_size)); -- plist_dict_set_item(fdict, "DLFileModificationDate", plist_new_date(st.st_mtime, 0)); -+ plist_dict_set_item(fdict, "DLFileModificationDate", -+ plist_new_date(st.st_mtime - MAC_EPOCH, 0)); - - plist_dict_set_item(dirlist, ep->d_name, fdict); - free(fpath); --- -2.14.1 - - -From 15173c59a00a8e9c154bd6787e35c243c383160e Mon Sep 17 00:00:00 2001 -From: BALATON Zoltan -Date: Wed, 23 Sep 2015 02:15:34 +0200 -Subject: [PATCH 14/65] Avoid potential NULL pointer dereference (leading to - segfault) if functions are called with NULL arguments - ---- - src/installation_proxy.c | 14 +++++++++----- - src/lockdown.c | 2 +- - 2 files changed, 10 insertions(+), 6 deletions(-) - -diff --git a/src/installation_proxy.c b/src/installation_proxy.c -index 8bde154..9f367aa 100644 ---- a/src/installation_proxy.c -+++ b/src/installation_proxy.c -@@ -847,11 +847,12 @@ LIBIMOBILEDEVICE_API instproxy_error_t instproxy_status_get_error(plist_t status - - LIBIMOBILEDEVICE_API void instproxy_status_get_name(plist_t status, char **name) - { -- *name = NULL; - if (name) { - plist_t node = plist_dict_get_item(status, "Status"); - if (node) { - plist_get_string_val(node, name); -+ } else { -+ *name = NULL; - } - } - } -@@ -907,10 +908,13 @@ LIBIMOBILEDEVICE_API void instproxy_status_get_current_list(plist_t status, uint - - LIBIMOBILEDEVICE_API void instproxy_command_get_name(plist_t command, char** name) - { -- *name = NULL; -- plist_t node = plist_dict_get_item(command, "Command"); -- if (node) { -- plist_get_string_val(node, name); -+ if (name) { -+ plist_t node = plist_dict_get_item(command, "Command"); -+ if (node) { -+ plist_get_string_val(node, name); -+ } else { -+ *name = NULL; -+ } - } - } - -diff --git a/src/lockdown.c b/src/lockdown.c -index 85124bd..d2e8c74 100644 ---- a/src/lockdown.c -+++ b/src/lockdown.c -@@ -637,7 +637,7 @@ LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_get_device_name(lockdownd_clien - - LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_client_new(idevice_t device, lockdownd_client_t *client, const char *label) - { -- if (!client) -+ if (!device || !client) - return LOCKDOWN_E_INVALID_ARG; - - static struct lockdownd_service_descriptor service = { --- -2.14.1 - - -From 692f7c9de72ca7fcaba51659972270d445751438 Mon Sep 17 00:00:00 2001 -From: BALATON Zoltan -Date: Wed, 23 Sep 2015 02:19:27 +0200 -Subject: [PATCH 15/65] Add new function to get the underlying file descriptor - of an idevice connection - ---- - include/libimobiledevice/libimobiledevice.h | 10 ++++++++++ - src/idevice.c | 16 ++++++++++++++++ - 2 files changed, 26 insertions(+) - -diff --git a/include/libimobiledevice/libimobiledevice.h b/include/libimobiledevice/libimobiledevice.h -index 016cadb..b125adf 100644 ---- a/include/libimobiledevice/libimobiledevice.h -+++ b/include/libimobiledevice/libimobiledevice.h -@@ -239,6 +239,16 @@ idevice_error_t idevice_connection_enable_ssl(idevice_connection_t connection); - */ - idevice_error_t idevice_connection_disable_ssl(idevice_connection_t connection); - -+/** -+ * Get the underlying file descriptor for a connection -+ * -+ * @param connection The connection to get fd of -+ * @param fd Pointer to an int where the fd is stored -+ * -+ * @return IDEVICE_E_SUCCESS if ok, otherwise an error code. -+ */ -+idevice_error_t idevice_connection_get_fd(idevice_connection_t connection, int *fd); -+ - /* misc */ - - /** -diff --git a/src/idevice.c b/src/idevice.c -index b776e84..5912aeb 100644 ---- a/src/idevice.c -+++ b/src/idevice.c -@@ -463,6 +463,22 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_receive(idevice_connecti - return internal_connection_receive(connection, data, len, recv_bytes); - } - -+LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_get_fd(idevice_connection_t connection, int *fd) -+{ -+ if (!connection || !fd) { -+ return IDEVICE_E_INVALID_ARG; -+ } -+ -+ idevice_error_t result = IDEVICE_E_UNKNOWN_ERROR; -+ if (connection->type == CONNECTION_USBMUXD) { -+ *fd = (int)(long)connection->data; -+ result = IDEVICE_E_SUCCESS; -+ } else { -+ debug_info("Unknown connection type %d", connection->type); -+ } -+ return result; -+} -+ - LIBIMOBILEDEVICE_API idevice_error_t idevice_get_handle(idevice_t device, uint32_t *handle) - { - if (!device) --- -2.14.1 - - -From cca7ce77d8bde998933ef8a753407b043806c1a6 Mon Sep 17 00:00:00 2001 -From: Matthias Ringwald -Date: Fri, 29 Apr 2016 20:27:32 +0200 -Subject: [PATCH 16/65] idevicedebug: Show error if container info not found - ---- - tools/idevicedebug.c | 18 ++++++++---------- - 1 file changed, 8 insertions(+), 10 deletions(-) - -diff --git a/tools/idevicedebug.c b/tools/idevicedebug.c -index b00893d..f18254a 100644 ---- a/tools/idevicedebug.c -+++ b/tools/idevicedebug.c -@@ -317,16 +317,14 @@ int main(int argc, char *argv[]) - instproxy_client_free(instproxy_client); - instproxy_client = NULL; - -- if (container) { -- if (plist_get_node_type(container) == PLIST_STRING) { -- plist_get_string_val(container, &working_directory); -- debug_info("working_directory: %s\n", working_directory); -- plist_free(container); -- } else { -- plist_free(container); -- fprintf(stderr, "Could not determine container path for bundle identifier %s.\n", bundle_identifier); -- goto cleanup; -- } -+ if (container && (plist_get_node_type(container) == PLIST_STRING)) { -+ plist_get_string_val(container, &working_directory); -+ debug_info("working_directory: %s\n", working_directory); -+ plist_free(container); -+ } else { -+ plist_free(container); -+ fprintf(stderr, "Could not determine container path for bundle identifier %s.\n", bundle_identifier); -+ goto cleanup; - } - - /* start and connect to debugserver */ --- -2.14.1 - - -From d29709f86ef66239551493b4b4a4fc7eb62771ce Mon Sep 17 00:00:00 2001 -From: Xiao Deng -Date: Fri, 29 Apr 2016 20:34:13 +0200 -Subject: [PATCH 17/65] diagnostics_relay: Plug small memory leak - ---- - src/diagnostics_relay.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/diagnostics_relay.c b/src/diagnostics_relay.c -index f67c4df..79e041e 100644 ---- a/src/diagnostics_relay.c -+++ b/src/diagnostics_relay.c -@@ -104,6 +104,7 @@ LIBIMOBILEDEVICE_API diagnostics_relay_error_t diagnostics_relay_client_free(dia - if (property_list_service_client_free(client->parent) != PROPERTY_LIST_SERVICE_E_SUCCESS) { - return DIAGNOSTICS_RELAY_E_UNKNOWN_ERROR; - } -+ free(client); - return DIAGNOSTICS_RELAY_E_SUCCESS; - } - --- -2.14.1 - - -From 11c1cd64edb750b3035c6b147e6b9712a6caefe2 Mon Sep 17 00:00:00 2001 -From: Xiao Deng -Date: Fri, 29 Apr 2016 20:34:52 +0200 -Subject: [PATCH 18/65] file_relay: Plug small memory leak - ---- - src/file_relay.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/file_relay.c b/src/file_relay.c -index 5055556..455855b 100644 ---- a/src/file_relay.c -+++ b/src/file_relay.c -@@ -59,6 +59,7 @@ LIBIMOBILEDEVICE_API file_relay_error_t file_relay_client_free(file_relay_client - if (property_list_service_client_free(client->parent) != PROPERTY_LIST_SERVICE_E_SUCCESS) { - return FILE_RELAY_E_UNKNOWN_ERROR; - } -+ free(client); - return FILE_RELAY_E_SUCCESS; - } - --- -2.14.1 - - -From ed48703dd92a223ae4a59393aade75b70367d833 Mon Sep 17 00:00:00 2001 -From: Kylie McClain -Date: Tue, 23 Jun 2015 04:28:41 -0400 -Subject: [PATCH 19/65] configure.ac: Don't always explicitly disable openssl - ---- - configure.ac | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/configure.ac b/configure.ac -index 43da458..bade848 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -120,7 +120,7 @@ AC_SUBST([CYTHON_SUB]) - AC_ARG_ENABLE([openssl], - [AS_HELP_STRING([--disable-openssl], - [Do not look for OpenSSL])], -- [use_openssl=no], -+ [use_openssl=$enableval], - [use_openssl=yes]) - - pkg_req_openssl="openssl >= 0.9.8" --- -2.14.1 - - -From e6486dbd29470939ed032972ca693888465e9ff4 Mon Sep 17 00:00:00 2001 -From: Arty Gus -Date: Fri, 29 Apr 2016 21:47:32 +0200 -Subject: [PATCH 21/65] configure.ac: Only check for pthread support on - non-win32 platforms - ---- - configure.ac | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/configure.ac b/configure.ac -index bade848..26fe819 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -37,7 +37,6 @@ AC_PROG_LIBTOOL - PKG_CHECK_MODULES(libusbmuxd, libusbmuxd >= $LIBUSBMUXD_VERSION) - PKG_CHECK_MODULES(libplist, libplist >= $LIBPLIST_VERSION) - PKG_CHECK_MODULES(libplistmm, libplist++ >= $LIBPLISTMM_VERSION) --AC_CHECK_LIB(pthread, [pthread_create, pthread_mutex_lock], [AC_SUBST(libpthread_LIBS,[-lpthread])], [AC_MSG_ERROR([libpthread is required to build libimobiledevice])]) - - # Checks for header files. - AC_HEADER_STDC -@@ -82,6 +81,10 @@ case ${host_os} in - esac - AM_CONDITIONAL(WIN32, test x$win32 = xtrue) - -+if test "x$win32" != xtrue; then -+ AC_CHECK_LIB(pthread, [pthread_create, pthread_mutex_lock], [AC_SUBST(libpthread_LIBS,[-lpthread])], [AC_MSG_ERROR([libpthread is required to build libimobiledevice])]) -+fi -+ - # Cython Python Bindings - AC_ARG_WITH([cython], - [AS_HELP_STRING([--without-cython], --- -2.14.1 - - -From 2a5868411c57e25802d2f16fd6b77601f10d0b72 Mon Sep 17 00:00:00 2001 -From: Nikos Mavrogiannopoulos -Date: Fri, 29 Apr 2016 22:58:34 +0200 -Subject: [PATCH 22/65] Updated gnutls certificate callback to new API - (backwards compatible) - ---- - src/idevice.c | 13 +++++++++++++ - 1 file changed, 13 insertions(+) - -diff --git a/src/idevice.c b/src/idevice.c -index 5912aeb..f2de6a3 100644 ---- a/src/idevice.c -+++ b/src/idevice.c -@@ -642,7 +642,11 @@ static const char *ssl_error_to_string(int e) - /** - * Internally used gnutls callback function that gets called during handshake. - */ -+#if GNUTLS_VERSION_NUMBER >= 0x020b07 -+static int internal_cert_callback(gnutls_session_t session, const gnutls_datum_t * req_ca_rdn, int nreqs, const gnutls_pk_algorithm_t * sign_algos, int sign_algos_length, gnutls_retr2_st * st) -+#else - static int internal_cert_callback(gnutls_session_t session, const gnutls_datum_t * req_ca_rdn, int nreqs, const gnutls_pk_algorithm_t * sign_algos, int sign_algos_length, gnutls_retr_st * st) -+#endif - { - int res = -1; - gnutls_certificate_type_t type = gnutls_certificate_type_get(session); -@@ -650,7 +654,12 @@ static int internal_cert_callback(gnutls_session_t session, const gnutls_datum_t - ssl_data_t ssl_data = (ssl_data_t)gnutls_session_get_ptr(session); - if (ssl_data && ssl_data->host_privkey && ssl_data->host_cert) { - debug_info("Passing certificate"); -+#if GNUTLS_VERSION_NUMBER >= 0x020b07 -+ st->cert_type = type; -+ st->key_type = GNUTLS_PRIVKEY_X509; -+#else - st->type = type; -+#endif - st->ncerts = 1; - st->cert.x509 = &ssl_data->host_cert; - st->key.x509 = ssl_data->host_privkey; -@@ -759,7 +768,11 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_enable_ssl(idevice_conne - debug_info("enabling SSL mode"); - errno = 0; - gnutls_certificate_allocate_credentials(&ssl_data_loc->certificate); -+#if GNUTLS_VERSION_NUMBER >= 0x020b07 -+ gnutls_certificate_set_retrieve_function(ssl_data_loc->certificate, internal_cert_callback); -+#else - gnutls_certificate_client_set_retrieve_function(ssl_data_loc->certificate, internal_cert_callback); -+#endif - gnutls_init(&ssl_data_loc->session, GNUTLS_CLIENT); - gnutls_priority_set_direct(ssl_data_loc->session, "NONE:+VERS-SSL3.0:+ANON-DH:+RSA:+AES-128-CBC:+AES-256-CBC:+SHA1:+MD5:+COMP-NULL", NULL); - gnutls_credentials_set(ssl_data_loc->session, GNUTLS_CRD_CERTIFICATE, ssl_data_loc->certificate); --- -2.14.1 - - -From 6ce120c168b0f0a0146e505649864b5b07dc5093 Mon Sep 17 00:00:00 2001 -From: Nikias Bassen -Date: Wed, 15 Jun 2016 02:01:36 +0200 -Subject: [PATCH 23/65] Fix SSL version negotiation with newer versions of - OpenSSL - ---- - src/idevice.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/idevice.c b/src/idevice.c -index f2de6a3..4e8c56e 100644 ---- a/src/idevice.c -+++ b/src/idevice.c -@@ -703,7 +703,7 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_enable_ssl(idevice_conne - } - BIO_set_fd(ssl_bio, (int)(long)connection->data, BIO_NOCLOSE); - -- SSL_CTX *ssl_ctx = SSL_CTX_new(SSLv3_method()); -+ SSL_CTX *ssl_ctx = SSL_CTX_new(SSLv23_method()); - if (ssl_ctx == NULL) { - debug_info("ERROR: Could not create SSL context."); - BIO_free(ssl_bio); --- -2.14.1 - - -From dc4c75d8a0a2ef557ac9ba0d2e080805621a3d98 Mon Sep 17 00:00:00 2001 -From: Nikias Bassen -Date: Thu, 16 Jun 2016 19:24:48 +0200 -Subject: [PATCH 24/65] Revert "Fix SSL version negotiation with newer versions - of OpenSSL" - -This reverts commit 6ce120c168b0f0a0146e505649864b5b07dc5093. -The change had the negative effect that connecting to older iOS devices wouldn't work anymore. ---- - src/idevice.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/idevice.c b/src/idevice.c -index 4e8c56e..f2de6a3 100644 ---- a/src/idevice.c -+++ b/src/idevice.c -@@ -703,7 +703,7 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_enable_ssl(idevice_conne - } - BIO_set_fd(ssl_bio, (int)(long)connection->data, BIO_NOCLOSE); - -- SSL_CTX *ssl_ctx = SSL_CTX_new(SSLv23_method()); -+ SSL_CTX *ssl_ctx = SSL_CTX_new(SSLv3_method()); - if (ssl_ctx == NULL) { - debug_info("ERROR: Could not create SSL context."); - BIO_free(ssl_bio); --- -2.14.1 - - -From 13bf235cac2201747de11652cf14fe2714ca0718 Mon Sep 17 00:00:00 2001 -From: David Weinstein -Date: Mon, 21 Mar 2016 17:45:59 -0400 -Subject: [PATCH 25/65] Fix SSL version negotiation for newer versions of - OpenSSL - -Depending on the OpenSSL version (and custom distribution patches), `SSLv3_method()` -would return NULL on some systems and also `SSLv23_method()` fails with some older -iOS versions... ---- - src/idevice.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/idevice.c b/src/idevice.c -index f2de6a3..1dcdae2 100644 ---- a/src/idevice.c -+++ b/src/idevice.c -@@ -703,7 +703,7 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_enable_ssl(idevice_conne - } - BIO_set_fd(ssl_bio, (int)(long)connection->data, BIO_NOCLOSE); - -- SSL_CTX *ssl_ctx = SSL_CTX_new(SSLv3_method()); -+ SSL_CTX *ssl_ctx = SSL_CTX_new(TLSv1_method()); - if (ssl_ctx == NULL) { - debug_info("ERROR: Could not create SSL context."); - BIO_free(ssl_bio); --- -2.14.1 - - -From a94c5c827a786844b56e8e36ddaed6239f32d86c Mon Sep 17 00:00:00 2001 -From: "Jay Freeman (saurik)" -Date: Wed, 27 Jul 2016 02:46:27 -0700 -Subject: [PATCH 26/65] lockdown: remove unnecessary check for pair record file - during pairing - -During device pairing the code in lockdownd_do_pair() is checking if there -is a pair record on disk for the current device, and then requests it from -usbmuxd. This additional check is not only unnecessary since usbmuxd can -obviously only return a pair record if it exists, but is also causing issues -on newer versions of macOS where /var/db/lockdown is mode 700. ---- - src/lockdown.c | 10 +++------- - 1 file changed, 3 insertions(+), 7 deletions(-) - -diff --git a/src/lockdown.c b/src/lockdown.c -index d2e8c74..904267e 100644 ---- a/src/lockdown.c -+++ b/src/lockdown.c -@@ -893,13 +893,9 @@ static lockdownd_error_t lockdownd_do_pair(lockdownd_client_t client, lockdownd_ - lockdownd_get_value(client, NULL, "WiFiAddress", &wifi_node); - } else { - /* use existing pair record */ -- if (userpref_has_pair_record(client->udid)) { -- userpref_read_pair_record(client->udid, &pair_record_plist); -- if (!pair_record_plist) { -- return LOCKDOWN_E_INVALID_CONF; -- } -- } else { -- return LOCKDOWN_E_INVALID_HOST_ID; -+ userpref_read_pair_record(client->udid, &pair_record_plist); -+ if (!pair_record_plist) { -+ return LOCKDOWN_E_INVALID_CONF; - } - } - } --- -2.14.1 - - -From 18811d92c940018aeb3916780960d8f085eb9f32 Mon Sep 17 00:00:00 2001 -From: "Jay Freeman (saurik)" -Date: Wed, 27 Jul 2016 02:46:47 -0700 -Subject: [PATCH 27/65] userpref: Remove obsoleted function - userpref_has_pair_record() - -Since pair records are meanwhile handled by usbmuxd there is no need to check -for the existence of a pair record on disk. Asking usbmuxd for a pair record of -a given UDID is sufficient to know if it exists or not. ---- - common/userpref.c | 29 ----------------------------- - 1 file changed, 29 deletions(-) - -diff --git a/common/userpref.c b/common/userpref.c -index f88a123..d22c7f5 100644 ---- a/common/userpref.c -+++ b/common/userpref.c -@@ -191,35 +191,6 @@ int userpref_read_system_buid(char **system_buid) - return res; - } - --/** -- * Determines whether this device has been connected to this system before. -- * -- * @param udid The device UDID as given by the device. -- * -- * @return 1 if the device has been connected previously to this configuration -- * or 0 otherwise. -- */ --int userpref_has_pair_record(const char *udid) --{ -- int ret = 0; -- const char *config_path = NULL; -- char *config_file = NULL; -- struct stat st; -- -- if (!udid) return 0; -- -- /* first get config file */ -- config_path = userpref_get_config_dir(); -- config_file = string_concat(config_path, DIR_SEP_S, udid, USERPREF_CONFIG_EXTENSION, NULL); -- -- if ((stat(config_file, &st) == 0) && S_ISREG(st.st_mode)) -- ret = 1; -- -- free(config_file); -- -- return ret; --} -- - /** - * Fills a list with UDIDs of devices that have been connected to this - * system before, i.e. for which a public key file exists. --- -2.14.1 - - -From 72643b2b83990b9cf97cc84b285b30763d44a72d Mon Sep 17 00:00:00 2001 -From: "Jay Freeman (saurik)" -Date: Tue, 2 Aug 2016 03:08:04 -0700 -Subject: [PATCH 28/65] idevice: Update GnuTLS code to support iOS 10 - -As of iOS 10 beta 4, the GnuTLS implementation idevice_connection_enable_ssl -needs to be updated to support TLS. Using +VERS-TLS-ALL did not work on some -of the devices I tested and I wasn't sure how to fix it, but +VERS-TLS1.0 is -working on every device I've tested: iOS 9.0.2, 10.0b4, 8.1.1, 6.0, and 3.0. ---- - src/idevice.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/idevice.c b/src/idevice.c -index 1dcdae2..b6dfe4e 100644 ---- a/src/idevice.c -+++ b/src/idevice.c -@@ -774,7 +774,7 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_enable_ssl(idevice_conne - gnutls_certificate_client_set_retrieve_function(ssl_data_loc->certificate, internal_cert_callback); - #endif - gnutls_init(&ssl_data_loc->session, GNUTLS_CLIENT); -- gnutls_priority_set_direct(ssl_data_loc->session, "NONE:+VERS-SSL3.0:+ANON-DH:+RSA:+AES-128-CBC:+AES-256-CBC:+SHA1:+MD5:+COMP-NULL", NULL); -+ 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); - gnutls_credentials_set(ssl_data_loc->session, GNUTLS_CRD_CERTIFICATE, ssl_data_loc->certificate); - gnutls_session_set_ptr(ssl_data_loc->session, ssl_data_loc); - --- -2.14.1 - - -From 00f8e5733f716da8032606566eac7a9e2e49514d Mon Sep 17 00:00:00 2001 -From: "Jay Freeman (saurik)" -Date: Tue, 9 Aug 2016 17:18:14 -0700 -Subject: [PATCH 29/65] lockdown: return LOCKDOWN_E_INVALID_HOST_ID when - missing pair record - -When the check of /var/db/lockdown was removed, lockdownd_do_pair started to -always return LOCKDOWN_E_INVALID_CONF instead of usually (but not always...) -returning LOCKDOWN_E_INVALID_HOST_ID for devices not currently paired. This -change not only breaks some third-party code, but also breaks the other code -in this library calling this function (lockdownd_client_new_with_handshake). ---- - src/lockdown.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/lockdown.c b/src/lockdown.c -index 904267e..cae950b 100644 ---- a/src/lockdown.c -+++ b/src/lockdown.c -@@ -895,7 +895,7 @@ static lockdownd_error_t lockdownd_do_pair(lockdownd_client_t client, lockdownd_ - /* use existing pair record */ - userpref_read_pair_record(client->udid, &pair_record_plist); - if (!pair_record_plist) { -- return LOCKDOWN_E_INVALID_CONF; -+ return LOCKDOWN_E_INVALID_HOST_ID; - } - } - } --- -2.14.1 - - -From 6aecc7228dbb30b4db48374ffb4ae4a1616bdd95 Mon Sep 17 00:00:00 2001 -From: Nikias Bassen -Date: Sun, 18 Sep 2016 16:18:20 +0200 -Subject: [PATCH 30/65] idevicebackup2: Fix removal of Snapshot dir during - backup with iOS 10+ - -DLMessageRemoveItems needs to recursively remove directories and this -commit implements that. ---- - tools/idevicebackup2.c | 101 ++++++++++++++++++++++++++++++++++++++----------- - 1 file changed, 78 insertions(+), 23 deletions(-) - -diff --git a/tools/idevicebackup2.c b/tools/idevicebackup2.c -index be5a1a0..c822d7f 100644 ---- a/tools/idevicebackup2.c -+++ b/tools/idevicebackup2.c -@@ -192,6 +192,74 @@ static int mkdir_with_parents(const char *dir, int mode) - return res; - } - -+static int remove_file(const char* path) -+{ -+ int e = 0; -+#ifdef WIN32 -+ if (!DeleteFile(path)) { -+ e = win32err_to_errno(GetLastError()); -+ } -+#else -+ if (remove(path) < 0) { -+ e = errno; -+ } -+#endif -+ return e; -+} -+ -+static int remove_directory(const char* path) -+{ -+ int e = 0; -+#ifdef WIN32 -+ if (!RemoveDirectory(path)) { -+ e = win32err_to_errno(GetLastError()); -+ } -+#else -+ if (remove(path) < 0) { -+ e = errno; -+ } -+#endif -+ return e; -+} -+ -+static int rmdir_recursive(const char* path) -+{ -+ DIR* cur_dir = opendir(path); -+ if (cur_dir) { -+ struct dirent* ep; -+ while ((ep = readdir(cur_dir))) { -+ if ((strcmp(ep->d_name, ".") == 0) || (strcmp(ep->d_name, "..") == 0)) { -+ continue; -+ } -+ char *fpath = string_build_path(path, ep->d_name, NULL); -+ if (fpath) { -+ struct stat st; -+ if (stat(fpath, &st) == 0) { -+ int res = 0; -+ if (S_ISDIR(st.st_mode)) { -+ res = rmdir_recursive(fpath); -+ } else { -+ res = remove_file(fpath); -+ } -+ if (res != 0) { -+ free(fpath); -+ closedir(cur_dir); -+ return res; -+ } -+ } else { -+ free(fpath); -+ closedir(cur_dir); -+ return errno; -+ } -+ } -+ free(fpath); -+ } -+ closedir(cur_dir); -+ } -+ -+ return remove_directory(path); -+} -+ - static plist_t mobilebackup_factory_info_plist_new(const char* udid, lockdownd_client_t lockdown, afc_client_t afc) - { - /* gather data from lockdown */ -@@ -1895,14 +1963,10 @@ checkpoint: - free(str); - char *oldpath = string_build_path(backup_directory, key, NULL); - --#ifdef WIN32 - if ((stat(newpath, &st) == 0) && S_ISDIR(st.st_mode)) -- RemoveDirectory(newpath); -+ rmdir_recursive(newpath); - else -- DeleteFile(newpath); --#else -- remove(newpath); --#endif -+ remove_file(newpath); - if (rename(oldpath, newpath) < 0) { - printf("Renameing '%s' to '%s' failed: %s (%d)\n", oldpath, newpath, strerror(errno), errno); - errcode = errno_to_device_error(errno); -@@ -1951,27 +2015,18 @@ checkpoint: - } - char *newpath = string_build_path(backup_directory, str, NULL); - free(str); --#ifdef WIN32 - int res = 0; -- if ((stat(newpath, &st) == 0) && S_ISDIR(st.st_mode)) -- res = RemoveDirectory(newpath); -- else -- res = DeleteFile(newpath); -- if (!res) { -- int e = win32err_to_errno(GetLastError()); -- if (!suppress_warning) -- printf("Could not remove '%s': %s (%d)\n", newpath, strerror(e), e); -- errcode = errno_to_device_error(e); -- errdesc = strerror(e); -+ if ((stat(newpath, &st) == 0) && S_ISDIR(st.st_mode)) { -+ res = rmdir_recursive(newpath); -+ } else { -+ res = remove_file(newpath); - } --#else -- if (remove(newpath) < 0) { -+ if (res != 0) { - if (!suppress_warning) -- printf("Could not remove '%s': %s (%d)\n", newpath, strerror(errno), errno); -- errcode = errno_to_device_error(errno); -- errdesc = strerror(errno); -+ printf("Could not remove '%s': %s (%d)\n", newpath, strerror(res), res); -+ errcode = errno_to_device_error(res); -+ errdesc = strerror(res); - } --#endif - free(newpath); - } - } --- -2.14.1 - - -From 98a096134b23be980a0aa56e775c5510f0e93595 Mon Sep 17 00:00:00 2001 -From: Nikias Bassen -Date: Sun, 18 Sep 2016 16:24:14 +0200 -Subject: [PATCH 31/65] idevicebackup2: Fix build on win32 after last commit - ---- - tools/idevicebackup2.c | 28 ++++++++++++++-------------- - 1 file changed, 14 insertions(+), 14 deletions(-) - -diff --git a/tools/idevicebackup2.c b/tools/idevicebackup2.c -index c822d7f..3b2c0af 100644 ---- a/tools/idevicebackup2.c -+++ b/tools/idevicebackup2.c -@@ -192,6 +192,20 @@ static int mkdir_with_parents(const char *dir, int mode) - return res; - } - -+#ifdef WIN32 -+static int win32err_to_errno(int err_value) -+{ -+ switch (err_value) { -+ case ERROR_FILE_NOT_FOUND: -+ return ENOENT; -+ case ERROR_ALREADY_EXISTS: -+ return EEXIST; -+ default: -+ return EFAULT; -+ } -+} -+#endif -+ - static int remove_file(const char* path) - { - int e = 0; -@@ -518,20 +532,6 @@ static int errno_to_device_error(int errno_value) - } - } - --#ifdef WIN32 --static int win32err_to_errno(int err_value) --{ -- switch (err_value) { -- case ERROR_FILE_NOT_FOUND: -- return ENOENT; -- case ERROR_ALREADY_EXISTS: -- return EEXIST; -- default: -- return EFAULT; -- } --} --#endif -- - static int mb2_handle_send_file(mobilebackup2_client_t mobilebackup2, const char *backup_dir, const char *path, plist_t *errplist) - { - uint32_t nlen = 0; --- -2.14.1 - - -From 3fc7a85778d85a1dda1c0c4bedc8467470468476 Mon Sep 17 00:00:00 2001 -From: Nikias Bassen -Date: Sun, 18 Sep 2016 16:42:26 +0200 -Subject: [PATCH 32/65] win32: Fix MinGW build by adding -lgdi32 to properly - link against OpenSSL - ---- - src/Makefile.am | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/Makefile.am b/src/Makefile.am -index da60386..5ced544 100644 ---- a/src/Makefile.am -+++ b/src/Makefile.am -@@ -32,7 +32,7 @@ libimobiledevice_la_SOURCES = idevice.c idevice.h \ - - if WIN32 - libimobiledevice_la_LDFLAGS += -avoid-version --libimobiledevice_la_LIBADD += -lole32 -lws2_32 -+libimobiledevice_la_LIBADD += -lole32 -lws2_32 -lgdi32 - endif - - pkgconfigdir = $(libdir)/pkgconfig --- -2.14.1 - - -From 00424f40574641d1360c9b1115770f5cc5d19a72 Mon Sep 17 00:00:00 2001 -From: Nikias Bassen -Date: Fri, 23 Sep 2016 20:07:48 +0200 -Subject: [PATCH 33/65] idevicebackup2: Add installed application info to - Info.plist during backup - -For newer iOS versions, apparently >= iOS 8, iTunes stores information -about installed applications inside of the Info.plist file. This -commit mimics that behavior. ---- - tools/idevicebackup2.c | 115 ++++++++++++++++++++++++++++++++++++++++++++++--- - 1 file changed, 110 insertions(+), 5 deletions(-) - -diff --git a/tools/idevicebackup2.c b/tools/idevicebackup2.c -index 3b2c0af..2c868d7 100644 ---- a/tools/idevicebackup2.c -+++ b/tools/idevicebackup2.c -@@ -40,6 +40,8 @@ - #include - #include - #include -+#include -+#include - #include "common/utils.h" - - #include -@@ -274,7 +276,24 @@ static int rmdir_recursive(const char* path) - return remove_directory(path); - } - --static plist_t mobilebackup_factory_info_plist_new(const char* udid, lockdownd_client_t lockdown, afc_client_t afc) -+static char* get_uuid() -+{ -+ const char *chars = "ABCDEF0123456789"; -+ int i = 0; -+ char *uuid = (char*)malloc(sizeof(char) * 32); -+ -+ srand(time(NULL)); -+ -+ for (i = 0; i < 32; i++) { -+ uuid[i] = chars[rand() % 16]; -+ } -+ -+ uuid[32] = '\0'; -+ -+ return uuid; -+} -+ -+static plist_t mobilebackup_factory_info_plist_new(const char* udid, idevice_t device, lockdownd_client_t lockdown, afc_client_t afc) - { - /* gather data from lockdown */ - plist_t value_node = NULL; -@@ -286,6 +305,74 @@ static plist_t mobilebackup_factory_info_plist_new(const char* udid, lockdownd_c - /* get basic device information in one go */ - lockdownd_get_value(lockdown, NULL, NULL, &root_node); - -+ /* get a list of installed user applications */ -+ plist_t app_dict = plist_new_dict(); -+ plist_t installed_apps = plist_new_array(); -+ instproxy_client_t ip = NULL; -+ if (instproxy_client_start_service(device, &ip, "idevicebackup2") == INSTPROXY_E_SUCCESS) { -+ plist_t client_opts = instproxy_client_options_new(); -+ instproxy_client_options_add(client_opts, "ApplicationType", "User", NULL); -+ instproxy_client_options_set_return_attributes(client_opts, "CFBundleIdentifier", "ApplicationSINF", "iTunesMetadata", NULL); -+ -+ plist_t apps = NULL; -+ instproxy_browse(ip, client_opts, &apps); -+ -+ sbservices_client_t sbs = NULL; -+ if (sbservices_client_start_service(device, &sbs, "idevicebackup2") != SBSERVICES_E_SUCCESS) { -+ printf("Couldn't establish sbservices connection. Continuing anyway.\n"); -+ } -+ -+ if (apps && (plist_get_node_type(apps) == PLIST_ARRAY)) { -+ uint32_t app_count = plist_array_get_size(apps); -+ uint32_t i; -+ time_t starttime = time(NULL); -+ for (i = 0; i < app_count; i++) { -+ plist_t app_entry = plist_array_get_item(apps, i); -+ plist_t bundle_id = plist_dict_get_item(app_entry, "CFBundleIdentifier"); -+ if (bundle_id) { -+ char *bundle_id_str = NULL; -+ plist_array_append_item(installed_apps, plist_copy(bundle_id)); -+ -+ plist_get_string_val(bundle_id, &bundle_id_str); -+ plist_t sinf = plist_dict_get_item(app_entry, "ApplicationSINF"); -+ plist_t meta = plist_dict_get_item(app_entry, "iTunesMetadata"); -+ if (sinf && meta) { -+ plist_t adict = plist_new_dict(); -+ plist_dict_set_item(adict, "ApplicationSINF", plist_copy(sinf)); -+ if (sbs) { -+ char *pngdata = NULL; -+ uint64_t pngsize = 0; -+ sbservices_get_icon_pngdata(sbs, bundle_id_str, &pngdata, &pngsize); -+ if (pngdata) { -+ plist_dict_set_item(adict, "PlaceholderIcon", plist_new_data(pngdata, pngsize)); -+ free(pngdata); -+ } -+ } -+ plist_dict_set_item(adict, "iTunesMetadata", plist_copy(meta)); -+ plist_dict_set_item(app_dict, bundle_id_str, adict); -+ } -+ } -+ if ((time(NULL) - starttime) > 5) { -+ // make sure our lockdown connection doesn't time out in case this takes longer -+ lockdownd_query_type(lockdown, NULL); -+ starttime = time(NULL); -+ } -+ } -+ } -+ plist_free(apps); -+ -+ if (sbs) { -+ sbservices_client_free(sbs); -+ } -+ -+ instproxy_client_options_free(client_opts); -+ -+ instproxy_client_free(ip); -+ } -+ -+ /* Applications */ -+ plist_dict_set_item(ret, "Applications", app_dict); -+ - /* set fields we understand */ - value_node = plist_dict_get_item(root_node, "BuildVersion"); - plist_dict_set_item(ret, "Build Version", plist_copy(value_node)); -@@ -294,8 +381,9 @@ static plist_t mobilebackup_factory_info_plist_new(const char* udid, lockdownd_c - plist_dict_set_item(ret, "Device Name", plist_copy(value_node)); - plist_dict_set_item(ret, "Display Name", plist_copy(value_node)); - -- /* FIXME: How is the GUID generated? */ -- plist_dict_set_item(ret, "GUID", plist_new_string("---")); -+ char *uuid = get_uuid(); -+ plist_dict_set_item(ret, "GUID", plist_new_string(uuid)); -+ free(uuid); - - value_node = plist_dict_get_item(root_node, "IntegratedCircuitCardIdentity"); - if (value_node) -@@ -305,13 +393,21 @@ static plist_t mobilebackup_factory_info_plist_new(const char* udid, lockdownd_c - if (value_node) - plist_dict_set_item(ret, "IMEI", plist_copy(value_node)); - -+ /* Installed Applications */ -+ plist_dict_set_item(ret, "Installed Applications", installed_apps); -+ - plist_dict_set_item(ret, "Last Backup Date", plist_new_date(time(NULL) - MAC_EPOCH, 0)); - -+ value_node = plist_dict_get_item(root_node, "MobileEquipmentIdentifier"); -+ plist_dict_set_item(ret, "MEID", plist_copy(value_node)); -+ - value_node = plist_dict_get_item(root_node, "PhoneNumber"); - if (value_node && (plist_get_node_type(value_node) == PLIST_STRING)) { - plist_dict_set_item(ret, "Phone Number", plist_copy(value_node)); - } - -+ /* FIXME Product Name */ -+ - value_node = plist_dict_get_item(root_node, "ProductType"); - plist_dict_set_item(ret, "Product Type", plist_copy(value_node)); - -@@ -349,6 +445,7 @@ static plist_t mobilebackup_factory_info_plist_new(const char* udid, lockdownd_c - "PhotosFolderAlbums", - "PhotosFolderName", - "PhotosFolderPrefs", -+ "VoiceMemos.plist", - "iPhotoAlbumPrefs", - "iTunesApplicationIDs", - "iTunesPrefs", -@@ -375,7 +472,15 @@ static plist_t mobilebackup_factory_info_plist_new(const char* udid, lockdownd_c - lockdownd_get_value(lockdown, "com.apple.iTunes", NULL, &itunes_settings); - plist_dict_set_item(ret, "iTunes Settings", itunes_settings ? itunes_settings : plist_new_dict()); - -- plist_dict_set_item(ret, "iTunes Version", plist_new_string("10.0.1")); -+ /* since we usually don't have iTunes, let's get the minimum required iTunes version from the device */ -+ value_node = NULL; -+ lockdownd_get_value(lockdown, "com.apple.mobile.iTunes", "MinITunesVersion", &value_node); -+ if (value_node) { -+ plist_dict_set_item(ret, "iTunes Version", plist_copy(value_node)); -+ plist_free(value_node); -+ } else { -+ plist_dict_set_item(ret, "iTunes Version", plist_new_string("10.0.1")); -+ } - - plist_free(root_node); - -@@ -1688,7 +1793,7 @@ checkpoint: - plist_free(info_plist); - info_plist = NULL; - } -- info_plist = mobilebackup_factory_info_plist_new(udid, lockdown, afc); -+ info_plist = mobilebackup_factory_info_plist_new(udid, device, lockdown, afc); - remove(info_path); - plist_write_to_filename(info_plist, info_path, PLIST_FORMAT_XML); - free(info_path); --- -2.14.1 - - -From 1fa41702b6c7b8b169a33b79125d3b24f23c2da8 Mon Sep 17 00:00:00 2001 -From: Nikias Bassen -Date: Tue, 4 Oct 2016 14:37:57 +0200 -Subject: [PATCH 34/65] idevicebackup2: Fix assertion occuring when copying - non-present MEID - ---- - tools/idevicebackup2.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/tools/idevicebackup2.c b/tools/idevicebackup2.c -index 2c868d7..eb78b06 100644 ---- a/tools/idevicebackup2.c -+++ b/tools/idevicebackup2.c -@@ -399,7 +399,8 @@ static plist_t mobilebackup_factory_info_plist_new(const char* udid, idevice_t d - plist_dict_set_item(ret, "Last Backup Date", plist_new_date(time(NULL) - MAC_EPOCH, 0)); - - value_node = plist_dict_get_item(root_node, "MobileEquipmentIdentifier"); -- plist_dict_set_item(ret, "MEID", plist_copy(value_node)); -+ if (value_node) -+ plist_dict_set_item(ret, "MEID", plist_copy(value_node)); - - value_node = plist_dict_get_item(root_node, "PhoneNumber"); - if (value_node && (plist_get_node_type(value_node) == PLIST_STRING)) { --- -2.14.1 - - -From c8c7adfd0e910ba5763777a25ce99f4f9143073f Mon Sep 17 00:00:00 2001 -From: Nikias Bassen -Date: Wed, 5 Oct 2016 17:07:09 +0200 -Subject: [PATCH 35/65] idevicebackup2: Suppress repeated printing of global - status when 100% is reached - ---- - tools/idevicebackup2.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/tools/idevicebackup2.c b/tools/idevicebackup2.c -index eb78b06..7b15897 100644 ---- a/tools/idevicebackup2.c -+++ b/tools/idevicebackup2.c -@@ -1999,6 +1999,7 @@ checkpoint: - int file_count = 0; - int errcode = 0; - const char *errdesc = NULL; -+ int progress_finished = 0; - - /* process series of DLMessage* operations */ - do { -@@ -2226,7 +2227,10 @@ checkpoint: - } - - /* print status */ -- if (overall_progress > 0) { -+ if ((overall_progress > 0) && !progress_finished) { -+ if (overall_progress >= 100.0f) { -+ progress_finished = 1; -+ } - print_progress_real(overall_progress, 0); - PRINT_VERBOSE(1, " Finished\n"); - } --- -2.14.1 - - -From 5dd8b52915cb5d9be91549366e989b28f3e29890 Mon Sep 17 00:00:00 2001 -From: Nikias Bassen -Date: Fri, 21 Oct 2016 14:29:56 +0200 -Subject: [PATCH 36/65] idevicebackup2: Use remove_file() wrapper instead of - remove() - ---- - tools/idevicebackup2.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/tools/idevicebackup2.c b/tools/idevicebackup2.c -index 7b15897..f47ff33 100644 ---- a/tools/idevicebackup2.c -+++ b/tools/idevicebackup2.c -@@ -960,7 +960,7 @@ static int mb2_handle_receive_files(mobilebackup2_client_t mobilebackup2, plist_ - PRINT_VERBOSE(1, "Found new flag %02x\n", code); - } - -- remove(bname); -+ remove_file(bname); - f = fopen(bname, "wb"); - while (f && (code == CODE_FILE_DATA)) { - blocksize = nlen-1; -@@ -1030,7 +1030,7 @@ static int mb2_handle_receive_files(mobilebackup2_client_t mobilebackup2, plist_ - fname = (char*)malloc(nlen-1); - mobilebackup2_receive_raw(mobilebackup2, fname, nlen-1, &r); - free(fname); -- remove(bname); -+ remove_file(bname); - } - - /* clean up */ -@@ -1795,7 +1795,7 @@ checkpoint: - info_plist = NULL; - } - info_plist = mobilebackup_factory_info_plist_new(udid, device, lockdown, afc); -- remove(info_path); -+ remove_file(info_path); - plist_write_to_filename(info_plist, info_path, PLIST_FORMAT_XML); - free(info_path); - --- -2.14.1 - - -From 2c16751bafb41a049e30f211c2a21c3b8c68259e Mon Sep 17 00:00:00 2001 -From: Nikias Bassen -Date: Fri, 21 Oct 2016 14:51:02 +0200 -Subject: [PATCH 37/65] idevicebackup2: Don't report an error when file to - remove doesn't exist - ---- - tools/idevicebackup2.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/tools/idevicebackup2.c b/tools/idevicebackup2.c -index f47ff33..d355200 100644 ---- a/tools/idevicebackup2.c -+++ b/tools/idevicebackup2.c -@@ -2128,7 +2128,7 @@ checkpoint: - } else { - res = remove_file(newpath); - } -- if (res != 0) { -+ if (res != 0 && res != ENOENT) { - if (!suppress_warning) - printf("Could not remove '%s': %s (%d)\n", newpath, strerror(res), res); - errcode = errno_to_device_error(res); --- -2.14.1 - - -From 8c37b9ca13211c197f3452356b73114c39f549fd Mon Sep 17 00:00:00 2001 -From: Nikias Bassen -Date: Wed, 2 Nov 2016 16:31:04 +0100 -Subject: [PATCH 38/65] idevicebackup2: Fix heap buffer out-of-bounds write - caused by wrong buffer size - ---- - tools/idevicebackup2.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/tools/idevicebackup2.c b/tools/idevicebackup2.c -index d355200..bb7f5c3 100644 ---- a/tools/idevicebackup2.c -+++ b/tools/idevicebackup2.c -@@ -280,7 +280,7 @@ static char* get_uuid() - { - const char *chars = "ABCDEF0123456789"; - int i = 0; -- char *uuid = (char*)malloc(sizeof(char) * 32); -+ char *uuid = (char*)malloc(sizeof(char) * 33); - - srand(time(NULL)); - --- -2.14.1 - - -From 23069d10341ce637fdad7321d447c53752dba48c Mon Sep 17 00:00:00 2001 -From: Nikias Bassen -Date: Fri, 4 Nov 2016 02:11:39 +0100 -Subject: [PATCH 39/65] userpref: [GnuTLS] Fix pairing record generation and - improve error handling - -In newer GnuTLS versions the parameters supplied to -gnutls_x509_privkey_import_rsa_raw() are actually checked for somewhat -sane values. Since we were passing the same values for all parameters, -this check fails and the device certificate is never generated. -However due to missing checks the pairing record was saved anyway, with -an empty device certificate. This led to TLS errors during communication, -leading to the "GnuTLS: Error in pull function" error message appearing -and the communication to fail. -This commit fixes the issue by passing some sane values, and also improves -the overall error handling during generation of the paring record. ---- - common/userpref.c | 85 +++++++++++++++++++++++++++++-------------------------- - 1 file changed, 45 insertions(+), 40 deletions(-) - -diff --git a/common/userpref.c b/common/userpref.c -index d22c7f5..3ae503a 100644 ---- a/common/userpref.c -+++ b/common/userpref.c -@@ -643,15 +643,13 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da - gnutls_x509_crt_export(host_cert, GNUTLS_X509_FMT_PEM, host_cert_pem.data, &host_cert_export_size); - host_cert_pem.size = host_cert_export_size; - -- ret = USERPREF_E_UNKNOWN_ERROR; -- - gnutls_datum_t modulus = { NULL, 0 }; - gnutls_datum_t exponent = { NULL, 0 }; - - /* now decode the PEM encoded key */ -- gnutls_datum_t der_pub_key; -- if (GNUTLS_E_SUCCESS == gnutls_pem_base64_decode_alloc("RSA PUBLIC KEY", &public_key, &der_pub_key)) { -- -+ gnutls_datum_t der_pub_key = { NULL, 0 }; -+ int gnutls_error = gnutls_pem_base64_decode_alloc("RSA PUBLIC KEY", &public_key, &der_pub_key); -+ if (GNUTLS_E_SUCCESS == gnutls_error) { - /* initalize asn.1 parser */ - ASN1_TYPE pkcs1 = ASN1_TYPE_EMPTY; - if (ASN1_SUCCESS == asn1_array2tree(pkcs1_asn1_tab, &pkcs1, NULL)) { -@@ -670,8 +668,14 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da - - ret1 = asn1_read_value(asn1_pub_key, "modulus", modulus.data, (int*)&modulus.size); - ret2 = asn1_read_value(asn1_pub_key, "publicExponent", exponent.data, (int*)&exponent.size); -- if (ASN1_SUCCESS == ret1 && ASN1_SUCCESS == ret2) -- ret = USERPREF_E_SUCCESS; -+ if (ret1 != ASN1_SUCCESS || ret2 != ASN1_SUCCESS) { -+ gnutls_free(modulus.data); -+ modulus.data = NULL; -+ modulus.size = 0; -+ gnutls_free(exponent.data); -+ exponent.data = NULL; -+ exponent.size = 0; -+ } - } - if (asn1_pub_key) - asn1_delete_structure(&asn1_pub_key); -@@ -679,12 +683,15 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da - if (pkcs1) - asn1_delete_structure(&pkcs1); - } else { -- debug_info("WARNING: Could not read public key"); -+ debug_info("ERROR: Could not parse public key: %s", gnutls_strerror(gnutls_error)); - } - -- /* now generate certificates */ -- if (USERPREF_E_SUCCESS == ret && 0 != modulus.size && 0 != exponent.size) { -- gnutls_datum_t essentially_null = { (unsigned char*)strdup("abababababababab"), strlen("abababababababab") }; -+ /* generate device certificate */ -+ if (modulus.data && 0 != modulus.size && exponent.data && 0 != exponent.size) { -+ -+ gnutls_datum_t prime_p = { (unsigned char*)"\x00\xca\x4a\x03\x13\xdf\x9d\x7a\xfd", 9 }; -+ gnutls_datum_t prime_q = { (unsigned char*)"\x00\xf2\xff\xe0\x15\xd1\x60\x37\x63", 9 }; -+ gnutls_datum_t coeff = { (unsigned char*)"\x32\x07\xf1\x68\x57\xdf\x9a\xf4", 8 }; - - gnutls_x509_privkey_t fake_privkey; - gnutls_x509_crt_t dev_cert; -@@ -692,8 +699,9 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da - gnutls_x509_privkey_init(&fake_privkey); - gnutls_x509_crt_init(&dev_cert); - -- if (GNUTLS_E_SUCCESS == gnutls_x509_privkey_import_rsa_raw(fake_privkey, &modulus, &exponent, &essentially_null, &essentially_null, &essentially_null, &essentially_null)) { -- /* generate device certificate */ -+ gnutls_error = gnutls_x509_privkey_import_rsa_raw(fake_privkey, &modulus, &exponent, &exponent, &prime_p, &prime_q, &coeff); -+ if (GNUTLS_E_SUCCESS == gnutls_error) { -+ /* now generate device certificate */ - gnutls_x509_crt_set_key(dev_cert, fake_privkey); - gnutls_x509_crt_set_serial(dev_cert, "\x00", 1); - gnutls_x509_crt_set_version(dev_cert, 3); -@@ -712,9 +720,8 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da - } - - gnutls_x509_crt_set_key_usage(dev_cert, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT); -- gnutls_x509_crt_sign(dev_cert, root_cert, root_privkey); -- -- if (USERPREF_E_SUCCESS == ret) { -+ gnutls_error = gnutls_x509_crt_sign(dev_cert, root_cert, root_privkey); -+ if (GNUTLS_E_SUCCESS == gnutls_error) { - /* if everything went well, export in PEM format */ - size_t export_size = 0; - gnutls_x509_crt_export(dev_cert, GNUTLS_X509_FMT_PEM, NULL, &export_size); -@@ -722,13 +729,11 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da - gnutls_x509_crt_export(dev_cert, GNUTLS_X509_FMT_PEM, dev_cert_pem.data, &export_size); - dev_cert_pem.size = export_size; - } else { -- debug_info("ERROR: Signing device certificate with root private key failed!"); -+ debug_info("ERROR: Signing device certificate with root private key failed: %s", gnutls_strerror(gnutls_error)); - } -+ } else { -+ debug_info("ERROR: Failed to import RSA key data: %s", gnutls_strerror(gnutls_error)); - } -- -- if (essentially_null.data) -- free(essentially_null.data); -- - gnutls_x509_crt_deinit(dev_cert); - gnutls_x509_privkey_deinit(fake_privkey); - } -@@ -743,27 +748,27 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da - - gnutls_free(der_pub_key.data); - #endif -- if (NULL != root_cert_pem.data && 0 != root_cert_pem.size && -- NULL != host_cert_pem.data && 0 != host_cert_pem.size) -+ -+ /* make sure that we have all we need */ -+ if (root_cert_pem.data && 0 != root_cert_pem.size -+ && root_key_pem.data && 0 != root_key_pem.size -+ && host_cert_pem.data && 0 != host_cert_pem.size -+ && host_key_pem.data && 0 != host_key_pem.size -+ && dev_cert_pem.data && 0 != dev_cert_pem.size) { -+ /* now set keys and certificates */ -+ pair_record_set_item_from_key_data(pair_record, USERPREF_DEVICE_CERTIFICATE_KEY, &dev_cert_pem); -+ pair_record_set_item_from_key_data(pair_record, USERPREF_HOST_PRIVATE_KEY_KEY, &host_key_pem); -+ pair_record_set_item_from_key_data(pair_record, USERPREF_HOST_CERTIFICATE_KEY, &host_cert_pem); -+ pair_record_set_item_from_key_data(pair_record, USERPREF_ROOT_PRIVATE_KEY_KEY, &root_key_pem); -+ pair_record_set_item_from_key_data(pair_record, USERPREF_ROOT_CERTIFICATE_KEY, &root_cert_pem); - ret = USERPREF_E_SUCCESS; -+ } - -- /* now set keys and certificates */ -- pair_record_set_item_from_key_data(pair_record, USERPREF_DEVICE_CERTIFICATE_KEY, &dev_cert_pem); -- pair_record_set_item_from_key_data(pair_record, USERPREF_HOST_PRIVATE_KEY_KEY, &host_key_pem); -- pair_record_set_item_from_key_data(pair_record, USERPREF_HOST_CERTIFICATE_KEY, &host_cert_pem); -- pair_record_set_item_from_key_data(pair_record, USERPREF_ROOT_PRIVATE_KEY_KEY, &root_key_pem); -- pair_record_set_item_from_key_data(pair_record, USERPREF_ROOT_CERTIFICATE_KEY, &root_cert_pem); -- -- if (dev_cert_pem.data) -- free(dev_cert_pem.data); -- if (root_key_pem.data) -- free(root_key_pem.data); -- if (root_cert_pem.data) -- free(root_cert_pem.data); -- if (host_key_pem.data) -- free(host_key_pem.data); -- if (host_cert_pem.data) -- free(host_cert_pem.data); -+ free(dev_cert_pem.data); -+ free(root_key_pem.data); -+ free(root_cert_pem.data); -+ free(host_key_pem.data); -+ free(host_cert_pem.data); - - return ret; - } --- -2.14.1 - - -From a1c728578930fb49e45497d1be7c9bc0c83607f1 Mon Sep 17 00:00:00 2001 -From: Nikias Bassen -Date: Sun, 27 Nov 2016 14:27:33 +0100 -Subject: [PATCH 40/65] idevicebackup2: Plug some small memory leaks - ---- - tools/idevicebackup2.c | 16 ++++++++-------- - 1 file changed, 8 insertions(+), 8 deletions(-) - -diff --git a/tools/idevicebackup2.c b/tools/idevicebackup2.c -index bb7f5c3..8dc32c5 100644 ---- a/tools/idevicebackup2.c -+++ b/tools/idevicebackup2.c -@@ -351,6 +351,7 @@ static plist_t mobilebackup_factory_info_plist_new(const char* udid, idevice_t d - plist_dict_set_item(adict, "iTunesMetadata", plist_copy(meta)); - plist_dict_set_item(app_dict, bundle_id_str, adict); - } -+ free(bundle_id_str); - } - if ((time(NULL) - starttime) > 5) { - // make sure our lockdown connection doesn't time out in case this takes longer -@@ -2003,10 +2004,8 @@ checkpoint: - - /* process series of DLMessage* operations */ - do { -- if (dlmsg) { -- free(dlmsg); -- dlmsg = NULL; -- } -+ free(dlmsg); -+ dlmsg = NULL; - mobilebackup2_receive_message(mobilebackup2, &message, &dlmsg); - if (!message || !dlmsg) { - PRINT_VERBOSE(1, "Device is not ready yet. Going to try again in 2 seconds...\n"); -@@ -2236,11 +2235,9 @@ checkpoint: - } - - files_out: -- if (message) -- plist_free(message); -+ plist_free(message); - message = NULL; -- if (dlmsg) -- free(dlmsg); -+ free(dlmsg); - dlmsg = NULL; - - if (quit_flag > 0) { -@@ -2256,6 +2253,9 @@ files_out: - } - } while (1); - -+ plist_free(message); -+ free(dlmsg); -+ - /* report operation status to user */ - switch (cmd) { - case CMD_CLOUD: --- -2.14.1 - - -From 2a9e6fe37467bfb13b415d7654f825269e08603f Mon Sep 17 00:00:00 2001 -From: Nikias Bassen -Date: Thu, 1 Dec 2016 03:43:05 +0100 -Subject: [PATCH 41/65] misagent: Add new misagent_copy_all() function - (introduced in iOS 9.3) - ---- - include/libimobiledevice/misagent.h | 24 +++++++++++++++++++++- - src/misagent.c | 40 +++++++++++++++++++++++++++++++++++++ - 2 files changed, 63 insertions(+), 1 deletion(-) - -diff --git a/include/libimobiledevice/misagent.h b/include/libimobiledevice/misagent.h -index 92165f2..09af57a 100644 ---- a/include/libimobiledevice/misagent.h -+++ b/include/libimobiledevice/misagent.h -@@ -101,7 +101,7 @@ misagent_error_t misagent_client_free(misagent_client_t client); - misagent_error_t misagent_install(misagent_client_t client, plist_t profile); - - /** -- * Retrieves an array of all installed provisioning profiles. -+ * Retrieves all installed provisioning profiles (iOS 9.2.1 or below). - * - * @param client The connected misagent to use. - * @param profiles Pointer to a plist_t that will be set to a PLIST_ARRAY -@@ -110,12 +110,34 @@ misagent_error_t misagent_install(misagent_client_t client, plist_t profile); - * @return MISAGENT_E_SUCCESS on success, MISAGENT_E_INVALID_ARG when - * client is invalid, or an MISAGENT_E_* error code otherwise. - * -+ * @note This API call only works with iOS 9.2.1 or below. -+ * For newer iOS versions use misagent_copy_all() instead. -+ * - * @note If no provisioning profiles are installed on the device, this function - * still returns MISAGENT_E_SUCCESS and profiles will just point to an - * empty array. - */ - misagent_error_t misagent_copy(misagent_client_t client, plist_t* profiles); - -+/** -+ * Retrieves all installed provisioning profiles (iOS 9.3 or higher). -+ * -+ * @param client The connected misagent to use. -+ * @param profiles Pointer to a plist_t that will be set to a PLIST_ARRAY -+ * if the function is successful. -+ * -+ * @return MISAGENT_E_SUCCESS on success, MISAGENT_E_INVALID_ARG when -+ * client is invalid, or an MISAGENT_E_* error code otherwise. -+ * -+ * @note This API call only works with iOS 9.3 or higher. -+ * For older iOS versions use misagent_copy() instead. -+ * -+ * @note If no provisioning profiles are installed on the device, this function -+ * still returns MISAGENT_E_SUCCESS and profiles will just point to an -+ * empty array. -+ */ -+misagent_error_t misagent_copy_all(misagent_client_t client, plist_t* profiles); -+ - /** - * Removes a given provisioning profile. - * -diff --git a/src/misagent.c b/src/misagent.c -index 2dd3451..095edba 100644 ---- a/src/misagent.c -+++ b/src/misagent.c -@@ -202,6 +202,46 @@ LIBIMOBILEDEVICE_API misagent_error_t misagent_copy(misagent_client_t client, pl - - } - -+LIBIMOBILEDEVICE_API misagent_error_t misagent_copy_all(misagent_client_t client, plist_t* profiles) -+{ -+ if (!client || !client->parent || !profiles) -+ return MISAGENT_E_INVALID_ARG; -+ -+ client->last_error = MISAGENT_E_UNKNOWN_ERROR; -+ -+ plist_t dict = plist_new_dict(); -+ plist_dict_set_item(dict, "MessageType", plist_new_string("CopyAll")); -+ plist_dict_set_item(dict, "ProfileType", plist_new_string("Provisioning")); -+ -+ misagent_error_t res = misagent_error(property_list_service_send_xml_plist(client->parent, dict)); -+ plist_free(dict); -+ dict = NULL; -+ -+ if (res != MISAGENT_E_SUCCESS) { -+ debug_info("could not send plist, error %d", res); -+ return res; -+ } -+ -+ res = misagent_error(property_list_service_receive_plist(client->parent, &dict)); -+ if (res != MISAGENT_E_SUCCESS) { -+ debug_info("could not receive response, error %d", res); -+ return res; -+ } -+ if (!dict) { -+ debug_info("could not get response plist"); -+ return MISAGENT_E_UNKNOWN_ERROR; -+ } -+ -+ res = misagent_check_result(dict, &client->last_error); -+ if (res == MISAGENT_E_SUCCESS) { -+ *profiles = plist_copy(plist_dict_get_item(dict, "Payload")); -+ } -+ plist_free(dict); -+ -+ return res; -+ -+} -+ - LIBIMOBILEDEVICE_API misagent_error_t misagent_remove(misagent_client_t client, const char* profileID) - { - if (!client || !client->parent || !profileID) --- -2.14.1 - - -From 76def2b68e7f2fbfc02315d29284fd74dabed8dc Mon Sep 17 00:00:00 2001 -From: Nikias Bassen -Date: Thu, 1 Dec 2016 03:51:15 +0100 -Subject: [PATCH 42/65] ideviceprovision: Use newer API to get list of profiles - on iOS 9.3+ - ---- - tools/ideviceprovision.c | 32 ++++++++++++++++++++++++++++++-- - 1 file changed, 30 insertions(+), 2 deletions(-) - -diff --git a/tools/ideviceprovision.c b/tools/ideviceprovision.c -index 4915c05..77c27dc 100644 ---- a/tools/ideviceprovision.c -+++ b/tools/ideviceprovision.c -@@ -3,7 +3,7 @@ - * Simple utility to install, get, or remove provisioning profiles - * to/from idevices - * -- * Copyright (c) 2012 Nikias Bassen, All Rights Reserved. -+ * Copyright (c) 2012-2016 Nikias Bassen, All Rights Reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public -@@ -390,6 +390,28 @@ int main(int argc, char *argv[]) - return -1; - } - -+ plist_t pver = NULL; -+ char *pver_s = NULL; -+ lockdownd_get_value(client, NULL, "ProductVersion", &pver); -+ if (pver && plist_get_node_type(pver) == PLIST_STRING) { -+ plist_get_string_val(pver, &pver_s); -+ } -+ plist_free(pver); -+ int product_version_major = 0; -+ int product_version_minor = 0; -+ int product_version_patch = 0; -+ if (pver_s) { -+ sscanf(pver_s, "%d.%d.%d", &product_version_major, &product_version_minor, &product_version_patch); -+ free(pver_s); -+ } -+ if (product_version_major == 0) { -+ fprintf(stderr, "ERROR: Could not determine the device's ProductVersion\n"); -+ lockdownd_client_free(client); -+ idevice_free(device); -+ return -1; -+ } -+ int product_version = ((product_version_major & 0xFF) << 16) | ((product_version_minor & 0xFF) << 8) | (product_version_patch & 0xFF); -+ - if (LOCKDOWN_E_SUCCESS != lockdownd_start_service(client, "com.apple.misagent", &service)) { - fprintf(stderr, "Could not start service \"com.apple.misagent\"\n"); - lockdownd_client_free(client); -@@ -437,7 +459,13 @@ int main(int argc, char *argv[]) - case OP_COPY: - { - plist_t profiles = NULL; -- if (misagent_copy(mis, &profiles) == MISAGENT_E_SUCCESS) { -+ misagent_error_t merr; -+ if (product_version < 0x090300) { -+ merr = misagent_copy(mis, &profiles); -+ } else { -+ merr = misagent_copy_all(mis, &profiles); -+ } -+ if (merr == MISAGENT_E_SUCCESS) { - uint32_t num_profiles = plist_array_get_size(profiles); - printf("Device has %d provisioning %s installed:\n", num_profiles, (num_profiles == 1) ? "profile" : "profiles"); - uint32_t j; --- -2.14.1 - - -From 9083475cd899a09040b265863fcfee0b390c89b3 Mon Sep 17 00:00:00 2001 -From: Nikias Bassen -Date: Thu, 1 Dec 2016 03:52:16 +0100 -Subject: [PATCH 43/65] ideviceprovision: Check output directory parameter for - 'copy' command and return exit code on error - ---- - tools/ideviceprovision.c | 22 +++++++++++++--------- - 1 file changed, 13 insertions(+), 9 deletions(-) - -diff --git a/tools/ideviceprovision.c b/tools/ideviceprovision.c -index 77c27dc..7938580 100644 ---- a/tools/ideviceprovision.c -+++ b/tools/ideviceprovision.c -@@ -27,6 +27,7 @@ - #include - #include - #include -+#include - - #ifdef WIN32 - #include -@@ -254,6 +255,7 @@ int main(int argc, char *argv[]) - lockdownd_service_descriptor_t service = NULL; - idevice_t device = NULL; - idevice_error_t ret = IDEVICE_E_UNKNOWN_ERROR; -+ int res = 0; - int i; - int op = -1; - int output_xml = 0; -@@ -338,7 +340,6 @@ int main(int argc, char *argv[]) - } - - if (op == OP_DUMP) { -- int res = 0; - unsigned char* profile_data = NULL; - unsigned int profile_size = 0; - if (profile_read_from_file(param, &profile_data, &profile_size) != 0) { -@@ -372,6 +373,12 @@ int main(int argc, char *argv[]) - plist_free(pl); - - return res; -+ } else if (op == OP_COPY) { -+ struct stat st; -+ if ((stat(param, &st) < 0) || !S_ISDIR(st.st_mode)) { -+ fprintf(stderr, "ERROR: %s does not exist or is not a directory!\n", param); -+ return -1; -+ } - } - - ret = idevice_new(&device, udid); -@@ -502,19 +509,16 @@ int main(int argc, char *argv[]) - fclose(f); - printf(" => %s\n", pfname); - } else { -- fprintf(stderr, "Could not open '%s' for writing\n", pfname); -+ fprintf(stderr, "Could not open '%s' for writing: %s\n", pfname, strerror(errno)); - } - } -- if (p_uuid) { -- free(p_uuid); -- } -- if (p_name) { -- free(p_name); -- } -+ free(p_uuid); -+ free(p_name); - } - } else { - int sc = misagent_get_status_code(mis); - fprintf(stderr, "Could not get installed profiles from device, status code: 0x%x\n", sc); -+ res = -1; - } - } - break; -@@ -534,6 +538,6 @@ int main(int argc, char *argv[]) - - idevice_free(device); - -- return 0; -+ return res; - } - --- -2.14.1 - - -From 9df4e695c55ddd319c5acaf7fa21f960afaa1e90 Mon Sep 17 00:00:00 2001 -From: Nikias Bassen -Date: Thu, 1 Dec 2016 03:56:00 +0100 -Subject: [PATCH 44/65] ideviceprovision: Allow copying single profiles instead - of all - ---- - tools/ideviceprovision.c | 38 ++++++++++++++++++++++++++++++++------ - 1 file changed, 32 insertions(+), 6 deletions(-) - -diff --git a/tools/ideviceprovision.c b/tools/ideviceprovision.c -index 7938580..79293bc 100644 ---- a/tools/ideviceprovision.c -+++ b/tools/ideviceprovision.c -@@ -27,6 +27,7 @@ - #include - #include - #include -+#include - #include - - #ifdef WIN32 -@@ -54,6 +55,9 @@ static void print_usage(int argc, char **argv) - printf(" copy PATH\tRetrieves all provisioning profiles from the device and\n"); - printf(" \tstores them into the existing directory specified by PATH.\n"); - printf(" \tThe files will be stored as UUID.mobileprovision\n"); -+ printf(" copy UUID PATH Retrieves the provisioning profile identified by UUID\n"); -+ printf(" \tfrom the device and stores it into the exisiting directory\n"); -+ printf(" \tspecified by PATH. The file will be stored as UUID.mobileprovision.\n"); - printf(" remove UUID\tRemoves the provisioning profile identified by UUID.\n"); - printf(" dump FILE\tPrints detailed information about the provisioning profile\n"); - printf(" \tspecified by FILE.\n\n"); -@@ -261,6 +265,7 @@ int main(int argc, char *argv[]) - int output_xml = 0; - const char* udid = NULL; - const char* param = NULL; -+ const char* param2 = NULL; - - /* parse cmdline args */ - for (i = 1; i < argc; i++) { -@@ -298,6 +303,10 @@ int main(int argc, char *argv[]) - } - param = argv[i]; - op = OP_COPY; -+ i++; -+ if (argv[i] && (strlen(argv[i]) > 0)) { -+ param2 = argv[i]; -+ } - continue; - } - else if (!strcmp(argv[i], "remove")) { -@@ -375,8 +384,9 @@ int main(int argc, char *argv[]) - return res; - } else if (op == OP_COPY) { - struct stat st; -- if ((stat(param, &st) < 0) || !S_ISDIR(st.st_mode)) { -- fprintf(stderr, "ERROR: %s does not exist or is not a directory!\n", param); -+ const char *checkdir = (param2) ? param2 : param; -+ if ((stat(checkdir, &st) < 0) || !S_ISDIR(st.st_mode)) { -+ fprintf(stderr, "ERROR: %s does not exist or is not a directory!\n", checkdir); - return -1; - } - } -@@ -473,10 +483,13 @@ int main(int argc, char *argv[]) - merr = misagent_copy_all(mis, &profiles); - } - if (merr == MISAGENT_E_SUCCESS) { -+ int found_match = 0; - uint32_t num_profiles = plist_array_get_size(profiles); -- printf("Device has %d provisioning %s installed:\n", num_profiles, (num_profiles == 1) ? "profile" : "profiles"); -+ if (op == OP_LIST || !param2) { -+ printf("Device has %d provisioning %s installed:\n", num_profiles, (num_profiles == 1) ? "profile" : "profiles"); -+ } - uint32_t j; -- for (j = 0; j < num_profiles; j++) { -+ for (j = 0; !found_match && j < num_profiles; j++) { - char* p_name = NULL; - char* p_uuid = NULL; - plist_t profile = plist_array_get_item(profiles, j); -@@ -492,13 +505,22 @@ int main(int argc, char *argv[]) - plist_get_string_val(node, &p_uuid); - } - } -+ if (param2) { -+ if (p_uuid && !strcmp(p_uuid, param)) { -+ found_match = 1; -+ } else { -+ free(p_uuid); -+ free(p_name); -+ continue; -+ } -+ } - printf("%s - %s\n", (p_uuid) ? p_uuid : "(unknown id)", (p_name) ? p_name : "(no name)"); - if (op == OP_COPY) { - char pfname[512]; - if (p_uuid) { -- sprintf(pfname, "%s/%s.mobileprovision", param, p_uuid); -+ sprintf(pfname, "%s/%s.mobileprovision", (param2) ? param2 : param, p_uuid); - } else { -- sprintf(pfname, "%s/profile%d.mobileprovision", param, j); -+ sprintf(pfname, "%s/profile%d.mobileprovision", (param2) ? param2 : param, j); - } - FILE* f = fopen(pfname, "wb"); - if (f) { -@@ -515,6 +537,10 @@ int main(int argc, char *argv[]) - free(p_uuid); - free(p_name); - } -+ if (param2 && !found_match) { -+ fprintf(stderr, "Profile '%s' was not found on the device.\n", param); -+ res = -1; -+ } - } else { - int sc = misagent_get_status_code(mis); - fprintf(stderr, "Could not get installed profiles from device, status code: 0x%x\n", sc); --- -2.14.1 - - -From d936514291c0f65ecb0448f3a4aad1b40517f468 Mon Sep 17 00:00:00 2001 -From: Nikias Bassen -Date: Thu, 15 Dec 2016 02:39:37 +0100 -Subject: [PATCH 45/65] ideviceprovision: Add new remove-all command to remove - all installed profiles at once - ---- - tools/ideviceprovision.c | 65 +++++++++++++++++++++++++++++++++++++++++++++--- - 1 file changed, 61 insertions(+), 4 deletions(-) - -diff --git a/tools/ideviceprovision.c b/tools/ideviceprovision.c -index 79293bc..26ec418 100644 ---- a/tools/ideviceprovision.c -+++ b/tools/ideviceprovision.c -@@ -59,6 +59,7 @@ static void print_usage(int argc, char **argv) - printf(" \tfrom the device and stores it into the exisiting directory\n"); - printf(" \tspecified by PATH. The file will be stored as UUID.mobileprovision.\n"); - printf(" remove UUID\tRemoves the provisioning profile identified by UUID.\n"); -+ printf(" remove-all\tRemoves all installed provisioning profiles.\n"); - printf(" dump FILE\tPrints detailed information about the provisioning profile\n"); - printf(" \tspecified by FILE.\n\n"); - printf(" The following OPTIONS are accepted:\n"); -@@ -319,6 +320,11 @@ int main(int argc, char *argv[]) - op = OP_REMOVE; - continue; - } -+ else if (!strcmp(argv[i], "remove-all")) { -+ i++; -+ op = OP_REMOVE; -+ continue; -+ } - else if (!strcmp(argv[i], "dump")) { - i++; - if (!argv[i] || (strlen(argv[i]) < 1)) { -@@ -546,14 +552,65 @@ int main(int argc, char *argv[]) - fprintf(stderr, "Could not get installed profiles from device, status code: 0x%x\n", sc); - res = -1; - } -+ plist_free(profiles); - } - break; - case OP_REMOVE: -- if (misagent_remove(mis, param) == MISAGENT_E_SUCCESS) { -- printf("Profile '%s' removed.\n", param); -+ if (param) { -+ /* remove specified provisioning profile */ -+ if (misagent_remove(mis, param) == MISAGENT_E_SUCCESS) { -+ printf("Profile '%s' removed.\n", param); -+ } else { -+ int sc = misagent_get_status_code(mis); -+ fprintf(stderr, "Could not remove profile '%s', status code 0x%x\n", param, sc); -+ } - } else { -- int sc = misagent_get_status_code(mis); -- fprintf(stderr, "Could not remove profile '%s', status code 0x%x\n", param, sc); -+ /* remove all provisioning profiles */ -+ plist_t profiles = NULL; -+ misagent_error_t merr; -+ if (product_version < 0x090300) { -+ merr = misagent_copy(mis, &profiles); -+ } else { -+ merr = misagent_copy_all(mis, &profiles); -+ } -+ if (merr == MISAGENT_E_SUCCESS) { -+ uint32_t j; -+ uint32_t num_removed = 0; -+ for (j = 0; j < plist_array_get_size(profiles); j++) { -+ char* p_name = NULL; -+ char* p_uuid = NULL; -+ plist_t profile = plist_array_get_item(profiles, j); -+ plist_t pl = profile_get_embedded_plist(profile); -+ if (pl && (plist_get_node_type(pl) == PLIST_DICT)) { -+ plist_t node; -+ node = plist_dict_get_item(pl, "Name"); -+ if (node && (plist_get_node_type(node) == PLIST_STRING)) { -+ plist_get_string_val(node, &p_name); -+ } -+ node = plist_dict_get_item(pl, "UUID"); -+ if (node && (plist_get_node_type(node) == PLIST_STRING)) { -+ plist_get_string_val(node, &p_uuid); -+ } -+ } -+ if (p_uuid) { -+ if (misagent_remove(mis, p_uuid) == MISAGENT_E_SUCCESS) { -+ printf("OK profile removed: %s - %s\n", p_uuid, (p_name) ? p_name : "(no name)"); -+ num_removed++; -+ } else { -+ int sc = misagent_get_status_code(mis); -+ printf("FAIL profile not removed: %s - %s (status code 0x%x)\n", p_uuid, (p_name) ? p_name : "(no name)", sc); -+ } -+ } -+ free(p_name); -+ free(p_uuid); -+ } -+ printf("%d profiles removed.\n", num_removed); -+ } else { -+ int sc = misagent_get_status_code(mis); -+ fprintf(stderr, "Could not get installed profiles from device, status code: 0x%x\n", sc); -+ res = -1; -+ } -+ plist_free(profiles); - } - break; - default: --- -2.14.1 - - -From c7f24a92f29180b50c0d92df34310f2179ba24cb Mon Sep 17 00:00:00 2001 -From: Nikias Bassen -Date: Thu, 15 Dec 2016 02:57:31 +0100 -Subject: [PATCH 46/65] idevicebackup2: Fix logical bug when checking for - success of backup operation - -The condition in line 2278 is incorrectly evaluated when -mb2_status_check_snapshot_state() isn't able to read the Status.plist file. -While `if (-1) { ... }` will be a 'false' condition, `if (1 && -1) { ... }` -will be 'true' which in this case would make idevicebackup2 assume the backup -was successful while it was not. -This commit fixes this issue by changing the default return value of -mb2_status_check_snapshot_state() to be 0 (false). - -Thanks to Xiao Deng for pointing out this issue! ---- - tools/idevicebackup2.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/tools/idevicebackup2.c b/tools/idevicebackup2.c -index 8dc32c5..e6c1d3f 100644 ---- a/tools/idevicebackup2.c -+++ b/tools/idevicebackup2.c -@@ -491,7 +491,7 @@ static plist_t mobilebackup_factory_info_plist_new(const char* udid, idevice_t d - - static int mb2_status_check_snapshot_state(const char *path, const char *udid, const char *matches) - { -- int ret = -1; -+ int ret = 0; - plist_t status_plist = NULL; - char *file_path = string_build_path(path, udid, "Status.plist", NULL); - --- -2.14.1 - - -From 2b8313181fb52cecd1db20f11c0da0c2c169050a Mon Sep 17 00:00:00 2001 -From: Nikias Bassen -Date: Wed, 21 Dec 2016 01:29:54 +0100 -Subject: [PATCH 47/65] cython: Make sure to pass correct CFLAGS for libplist - ---- - cython/Makefile.am | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/cython/Makefile.am b/cython/Makefile.am -index 94ff728..fb9a2e4 100644 ---- a/cython/Makefile.am -+++ b/cython/Makefile.am -@@ -1,6 +1,6 @@ - AM_CPPFLAGS = -I$(top_srcdir)/include - --AM_CFLAGS = $(GLOBAL_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(openssl_CFLAGS) $(LFS_CFLAGS) -+AM_CFLAGS = $(GLOBAL_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(openssl_CFLAGS) $(libplist_CFLAGS) $(LFS_CFLAGS) - AM_LDFLAGS = $(libgnutls_LIBS) $(libtasn1_LIBS) $(openssl_LIBS) $(libplist_LIBS) - - if HAVE_CYTHON --- -2.14.1 - - -From a80ba9363b4dc0ea1bcdad152cf2cdc974636ad6 Mon Sep 17 00:00:00 2001 -From: Nikias Bassen -Date: Thu, 22 Dec 2016 14:40:46 +0100 -Subject: [PATCH 48/65] ideviceprovision: Fix ASN1 parsing for large - provisioning profiles - ---- - tools/ideviceprovision.c | 47 +++++++++++++++++++++++++++++++++++------------ - 1 file changed, 35 insertions(+), 12 deletions(-) - -diff --git a/tools/ideviceprovision.c b/tools/ideviceprovision.c -index 26ec418..db00702 100644 ---- a/tools/ideviceprovision.c -+++ b/tools/ideviceprovision.c -@@ -87,30 +87,47 @@ enum { - - static void asn1_next_item(unsigned char** p) - { -- if (*(*p+1) & 0x80) { -- *p += 4; -+ char bsize = *(*p+1); -+ if (bsize & 0x80) { -+ *p += 2 + (bsize & 0xF); - } else { - *p += 3; - } - } - --static int asn1_item_get_size(unsigned char* p) -+static size_t asn1_item_get_size(unsigned char* p) - { -- int res = 0; -- if (*(p+1) & 0x80) { -+ size_t res = 0; -+ char bsize = *(p+1); -+ if (bsize & 0x80) { - uint16_t ws = 0; -- memcpy(&ws, p+2, 2); -- ws = ntohs(ws); -- res = ws; -+ uint32_t ds = 0; -+ switch (bsize & 0xF) { -+ case 2: -+ ws = *(uint16_t*)(p+2); -+ res = ntohs(ws); -+ break; -+ case 3: -+ ds = *(uint32_t*)(p+2); -+ res = ntohl(ds) >> 8; -+ break; -+ case 4: -+ ds = *(uint32_t*)(p+2); -+ res = ntohl(ds); -+ break; -+ default: -+ fprintf(stderr, "ERROR: Invalid or unimplemented byte size %d\n", bsize & 0xF); -+ break; -+ } - } else { -- res = (int) *(p+1); -+ res = (int)bsize; - } - return res; - } - - static void asn1_skip_item(unsigned char** p) - { -- int sz = asn1_item_get_size(*p); -+ size_t sz = asn1_item_get_size(*p); - *p += 2; - *p += sz; - } -@@ -136,8 +153,14 @@ static plist_t profile_get_embedded_plist(plist_t profile) - fprintf(stderr, "%s: unexpected profile data (0)\n", __func__); - return NULL; - } -- uint16_t slen = asn1_item_get_size(pp); -- if (slen+4 != (uint16_t)blen) { -+ size_t slen = asn1_item_get_size(pp); -+ char bsize = *(pp+1); -+ if (bsize & 0x80) { -+ slen += 2 + bsize & 0xF; -+ } else { -+ slen += 3; -+ } -+ if (slen != blen) { - free(bbuf); - fprintf(stderr, "%s: unexpected profile data (1)\n", __func__); - return NULL; --- -2.14.1 - - -From 038bb5902fcc4e981fb349fbba629eab2bdf93ff Mon Sep 17 00:00:00 2001 -From: Nikias Bassen -Date: Sat, 31 Dec 2016 02:59:36 +0100 -Subject: [PATCH 49/65] Add ax_pthread.m4 for proper pthread cflags/ldflags - ---- - configure.ac | 18 +-- - m4/ax_pthread.m4 | 485 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ - src/Makefile.am | 4 +- - 3 files changed, 495 insertions(+), 12 deletions(-) - create mode 100644 m4/ax_pthread.m4 - -diff --git a/configure.ac b/configure.ac -index 26fe819..e41baa3 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -66,25 +66,23 @@ if test "x$ac_cv_have_endian_h" = "xno"; then - fi - - # Check for operating system --AC_MSG_CHECKING([whether to enable WIN32 build settings]) -+AC_MSG_CHECKING([whether we need platform-specific build settings]) - case ${host_os} in - *mingw32*|*cygwin*) -- win32=true - AC_MSG_RESULT([yes]) -- AC_CHECK_TOOL([WINDRES], [windres], AC_MSG_ERROR([windres not found])) -- AC_SUBST(WINDRES) -+ win32=true - ;; -- *) -- win32=false -+ darwin*) - AC_MSG_RESULT([no]) - ;; -+ *) -+ AC_MSG_RESULT([yes]) -+ AX_PTHREAD([], [AC_MSG_ERROR([pthread is required to build $PACKAGE_NAME])]) -+ AC_CHECK_LIB(pthread, [pthread_once], [], [AC_MSG_ERROR([pthread with pthread_once required to build $PACKAGE_NAME])]) -+ ;; - esac - AM_CONDITIONAL(WIN32, test x$win32 = xtrue) - --if test "x$win32" != xtrue; then -- AC_CHECK_LIB(pthread, [pthread_create, pthread_mutex_lock], [AC_SUBST(libpthread_LIBS,[-lpthread])], [AC_MSG_ERROR([libpthread is required to build libimobiledevice])]) --fi -- - # Cython Python Bindings - AC_ARG_WITH([cython], - [AS_HELP_STRING([--without-cython], -diff --git a/m4/ax_pthread.m4 b/m4/ax_pthread.m4 -new file mode 100644 -index 0000000..4c4051e ---- /dev/null -+++ b/m4/ax_pthread.m4 -@@ -0,0 +1,485 @@ -+# =========================================================================== -+# http://www.gnu.org/software/autoconf-archive/ax_pthread.html -+# =========================================================================== -+# -+# SYNOPSIS -+# -+# AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) -+# -+# DESCRIPTION -+# -+# This macro figures out how to build C programs using POSIX threads. It -+# sets the PTHREAD_LIBS output variable to the threads library and linker -+# flags, and the PTHREAD_CFLAGS output variable to any special C compiler -+# flags that are needed. (The user can also force certain compiler -+# flags/libs to be tested by setting these environment variables.) -+# -+# Also sets PTHREAD_CC to any special C compiler that is needed for -+# multi-threaded programs (defaults to the value of CC otherwise). (This -+# is necessary on AIX to use the special cc_r compiler alias.) -+# -+# NOTE: You are assumed to not only compile your program with these flags, -+# but also to link with them as well. For example, you might link with -+# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS -+# -+# If you are only building threaded programs, you may wish to use these -+# variables in your default LIBS, CFLAGS, and CC: -+# -+# LIBS="$PTHREAD_LIBS $LIBS" -+# CFLAGS="$CFLAGS $PTHREAD_CFLAGS" -+# CC="$PTHREAD_CC" -+# -+# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant -+# has a nonstandard name, this macro defines PTHREAD_CREATE_JOINABLE to -+# that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX). -+# -+# Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the -+# PTHREAD_PRIO_INHERIT symbol is defined when compiling with -+# PTHREAD_CFLAGS. -+# -+# ACTION-IF-FOUND is a list of shell commands to run if a threads library -+# is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it -+# is not found. If ACTION-IF-FOUND is not specified, the default action -+# will define HAVE_PTHREAD. -+# -+# Please let the authors know if this macro fails on any platform, or if -+# you have any other suggestions or comments. This macro was based on work -+# by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help -+# from M. Frigo), as well as ac_pthread and hb_pthread macros posted by -+# Alejandro Forero Cuervo to the autoconf macro repository. We are also -+# grateful for the helpful feedback of numerous users. -+# -+# Updated for Autoconf 2.68 by Daniel Richard G. -+# -+# LICENSE -+# -+# Copyright (c) 2008 Steven G. Johnson -+# Copyright (c) 2011 Daniel Richard G. -+# -+# This program is free software: you can redistribute it and/or modify it -+# under the terms of the GNU General Public License as published by the -+# Free Software Foundation, either version 3 of the License, or (at your -+# option) any later version. -+# -+# This program is distributed in the hope that it will be useful, but -+# WITHOUT ANY WARRANTY; without even the implied warranty of -+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -+# Public License for more details. -+# -+# You should have received a copy of the GNU General Public License along -+# with this program. If not, see . -+# -+# As a special exception, the respective Autoconf Macro's copyright owner -+# gives unlimited permission to copy, distribute and modify the configure -+# scripts that are the output of Autoconf when processing the Macro. You -+# need not follow the terms of the GNU General Public License when using -+# or distributing such scripts, even though portions of the text of the -+# Macro appear in them. The GNU General Public License (GPL) does govern -+# all other use of the material that constitutes the Autoconf Macro. -+# -+# This special exception to the GPL applies to versions of the Autoconf -+# Macro released by the Autoconf Archive. When you make and distribute a -+# modified version of the Autoconf Macro, you may extend this special -+# exception to the GPL to apply to your modified version as well. -+ -+#serial 23 -+ -+AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD]) -+AC_DEFUN([AX_PTHREAD], [ -+AC_REQUIRE([AC_CANONICAL_HOST]) -+AC_REQUIRE([AC_PROG_CC]) -+AC_REQUIRE([AC_PROG_SED]) -+AC_LANG_PUSH([C]) -+ax_pthread_ok=no -+ -+# We used to check for pthread.h first, but this fails if pthread.h -+# requires special compiler flags (e.g. on Tru64 or Sequent). -+# It gets checked for in the link test anyway. -+ -+# First of all, check if the user has set any of the PTHREAD_LIBS, -+# etcetera environment variables, and if threads linking works using -+# them: -+if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then -+ ax_pthread_save_CC="$CC" -+ ax_pthread_save_CFLAGS="$CFLAGS" -+ ax_pthread_save_LIBS="$LIBS" -+ AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"]) -+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS" -+ LIBS="$PTHREAD_LIBS $LIBS" -+ AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS]) -+ AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_join])], [ax_pthread_ok=yes]) -+ AC_MSG_RESULT([$ax_pthread_ok]) -+ if test "x$ax_pthread_ok" = "xno"; then -+ PTHREAD_LIBS="" -+ PTHREAD_CFLAGS="" -+ fi -+ CC="$ax_pthread_save_CC" -+ CFLAGS="$ax_pthread_save_CFLAGS" -+ LIBS="$ax_pthread_save_LIBS" -+fi -+ -+# We must check for the threads library under a number of different -+# names; the ordering is very important because some systems -+# (e.g. DEC) have both -lpthread and -lpthreads, where one of the -+# libraries is broken (non-POSIX). -+ -+# Create a list of thread flags to try. Items starting with a "-" are -+# C compiler flags, and other items are library names, except for "none" -+# which indicates that we try without any flags at all, and "pthread-config" -+# which is a program returning the flags for the Pth emulation library. -+ -+ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" -+ -+# The ordering *is* (sometimes) important. Some notes on the -+# individual items follow: -+ -+# pthreads: AIX (must check this before -lpthread) -+# none: in case threads are in libc; should be tried before -Kthread and -+# other compiler flags to prevent continual compiler warnings -+# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) -+# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64 -+# (Note: HP C rejects this with "bad form for `-t' option") -+# -pthreads: Solaris/gcc (Note: HP C also rejects) -+# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it -+# doesn't hurt to check since this sometimes defines pthreads and -+# -D_REENTRANT too), HP C (must be checked before -lpthread, which -+# is present but should not be used directly; and before -mthreads, -+# because the compiler interprets this as "-mt" + "-hreads") -+# -mthreads: Mingw32/gcc, Lynx/gcc -+# pthread: Linux, etcetera -+# --thread-safe: KAI C++ -+# pthread-config: use pthread-config program (for GNU Pth library) -+ -+case $host_os in -+ -+ freebsd*) -+ -+ # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) -+ # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) -+ -+ ax_pthread_flags="-kthread lthread $ax_pthread_flags" -+ ;; -+ -+ hpux*) -+ -+ # From the cc(1) man page: "[-mt] Sets various -D flags to enable -+ # multi-threading and also sets -lpthread." -+ -+ ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags" -+ ;; -+ -+ openedition*) -+ -+ # IBM z/OS requires a feature-test macro to be defined in order to -+ # enable POSIX threads at all, so give the user a hint if this is -+ # not set. (We don't define these ourselves, as they can affect -+ # other portions of the system API in unpredictable ways.) -+ -+ AC_EGREP_CPP([AX_PTHREAD_ZOS_MISSING], -+ [ -+# if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS) -+ AX_PTHREAD_ZOS_MISSING -+# endif -+ ], -+ [AC_MSG_WARN([IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support.])]) -+ ;; -+ -+ solaris*) -+ -+ # On Solaris (at least, for some versions), libc contains stubbed -+ # (non-functional) versions of the pthreads routines, so link-based -+ # tests will erroneously succeed. (N.B.: The stubs are missing -+ # pthread_cleanup_push, or rather a function called by this macro, -+ # so we could check for that, but who knows whether they'll stub -+ # that too in a future libc.) So we'll check first for the -+ # standard Solaris way of linking pthreads (-mt -lpthread). -+ -+ ax_pthread_flags="-mt,pthread pthread $ax_pthread_flags" -+ ;; -+esac -+ -+# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC) -+ -+AS_IF([test "x$GCC" = "xyes"], -+ [ax_pthread_flags="-pthread -pthreads $ax_pthread_flags"]) -+ -+# The presence of a feature test macro requesting re-entrant function -+# definitions is, on some systems, a strong hint that pthreads support is -+# correctly enabled -+ -+case $host_os in -+ darwin* | hpux* | linux* | osf* | solaris*) -+ ax_pthread_check_macro="_REENTRANT" -+ ;; -+ -+ aix*) -+ ax_pthread_check_macro="_THREAD_SAFE" -+ ;; -+ -+ *) -+ ax_pthread_check_macro="--" -+ ;; -+esac -+AS_IF([test "x$ax_pthread_check_macro" = "x--"], -+ [ax_pthread_check_cond=0], -+ [ax_pthread_check_cond="!defined($ax_pthread_check_macro)"]) -+ -+# Are we compiling with Clang? -+ -+AC_CACHE_CHECK([whether $CC is Clang], -+ [ax_cv_PTHREAD_CLANG], -+ [ax_cv_PTHREAD_CLANG=no -+ # Note that Autoconf sets GCC=yes for Clang as well as GCC -+ if test "x$GCC" = "xyes"; then -+ AC_EGREP_CPP([AX_PTHREAD_CC_IS_CLANG], -+ [/* Note: Clang 2.7 lacks __clang_[a-z]+__ */ -+# if defined(__clang__) && defined(__llvm__) -+ AX_PTHREAD_CC_IS_CLANG -+# endif -+ ], -+ [ax_cv_PTHREAD_CLANG=yes]) -+ fi -+ ]) -+ax_pthread_clang="$ax_cv_PTHREAD_CLANG" -+ -+ax_pthread_clang_warning=no -+ -+# Clang needs special handling, because older versions handle the -pthread -+# option in a rather... idiosyncratic way -+ -+if test "x$ax_pthread_clang" = "xyes"; then -+ -+ # Clang takes -pthread; it has never supported any other flag -+ -+ # (Note 1: This will need to be revisited if a system that Clang -+ # supports has POSIX threads in a separate library. This tends not -+ # to be the way of modern systems, but it's conceivable.) -+ -+ # (Note 2: On some systems, notably Darwin, -pthread is not needed -+ # to get POSIX threads support; the API is always present and -+ # active. We could reasonably leave PTHREAD_CFLAGS empty. But -+ # -pthread does define _REENTRANT, and while the Darwin headers -+ # ignore this macro, third-party headers might not.) -+ -+ PTHREAD_CFLAGS="-pthread" -+ PTHREAD_LIBS= -+ -+ ax_pthread_ok=yes -+ -+ # However, older versions of Clang make a point of warning the user -+ # that, in an invocation where only linking and no compilation is -+ # taking place, the -pthread option has no effect ("argument unused -+ # during compilation"). They expect -pthread to be passed in only -+ # when source code is being compiled. -+ # -+ # Problem is, this is at odds with the way Automake and most other -+ # C build frameworks function, which is that the same flags used in -+ # compilation (CFLAGS) are also used in linking. Many systems -+ # supported by AX_PTHREAD require exactly this for POSIX threads -+ # support, and in fact it is often not straightforward to specify a -+ # flag that is used only in the compilation phase and not in -+ # linking. Such a scenario is extremely rare in practice. -+ # -+ # Even though use of the -pthread flag in linking would only print -+ # a warning, this can be a nuisance for well-run software projects -+ # that build with -Werror. So if the active version of Clang has -+ # this misfeature, we search for an option to squash it. -+ -+ AC_CACHE_CHECK([whether Clang needs flag to prevent "argument unused" warning when linking with -pthread], -+ [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG], -+ [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown -+ # Create an alternate version of $ac_link that compiles and -+ # links in two steps (.c -> .o, .o -> exe) instead of one -+ # (.c -> exe), because the warning occurs only in the second -+ # step -+ ax_pthread_save_ac_link="$ac_link" -+ ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g' -+ ax_pthread_link_step=`$as_echo "$ac_link" | sed "$ax_pthread_sed"` -+ ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)" -+ ax_pthread_save_CFLAGS="$CFLAGS" -+ for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do -+ AS_IF([test "x$ax_pthread_try" = "xunknown"], [break]) -+ CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS" -+ ac_link="$ax_pthread_save_ac_link" -+ AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], -+ [ac_link="$ax_pthread_2step_ac_link" -+ AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], -+ [break]) -+ ]) -+ done -+ ac_link="$ax_pthread_save_ac_link" -+ CFLAGS="$ax_pthread_save_CFLAGS" -+ AS_IF([test "x$ax_pthread_try" = "x"], [ax_pthread_try=no]) -+ ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try" -+ ]) -+ -+ case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in -+ no | unknown) ;; -+ *) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;; -+ esac -+ -+fi # $ax_pthread_clang = yes -+ -+if test "x$ax_pthread_ok" = "xno"; then -+for ax_pthread_try_flag in $ax_pthread_flags; do -+ -+ case $ax_pthread_try_flag in -+ none) -+ AC_MSG_CHECKING([whether pthreads work without any flags]) -+ ;; -+ -+ -mt,pthread) -+ AC_MSG_CHECKING([whether pthreads work with -mt -lpthread]) -+ PTHREAD_CFLAGS="-mt" -+ PTHREAD_LIBS="-lpthread" -+ ;; -+ -+ -*) -+ AC_MSG_CHECKING([whether pthreads work with $ax_pthread_try_flag]) -+ PTHREAD_CFLAGS="$ax_pthread_try_flag" -+ ;; -+ -+ pthread-config) -+ AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no]) -+ AS_IF([test "x$ax_pthread_config" = "xno"], [continue]) -+ PTHREAD_CFLAGS="`pthread-config --cflags`" -+ PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" -+ ;; -+ -+ *) -+ AC_MSG_CHECKING([for the pthreads library -l$ax_pthread_try_flag]) -+ PTHREAD_LIBS="-l$ax_pthread_try_flag" -+ ;; -+ esac -+ -+ ax_pthread_save_CFLAGS="$CFLAGS" -+ ax_pthread_save_LIBS="$LIBS" -+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS" -+ LIBS="$PTHREAD_LIBS $LIBS" -+ -+ # Check for various functions. We must include pthread.h, -+ # since some functions may be macros. (On the Sequent, we -+ # need a special flag -Kthread to make this header compile.) -+ # We check for pthread_join because it is in -lpthread on IRIX -+ # while pthread_create is in libc. We check for pthread_attr_init -+ # due to DEC craziness with -lpthreads. We check for -+ # pthread_cleanup_push because it is one of the few pthread -+ # functions on Solaris that doesn't have a non-functional libc stub. -+ # We try pthread_create on general principles. -+ -+ AC_LINK_IFELSE([AC_LANG_PROGRAM([#include -+# if $ax_pthread_check_cond -+# error "$ax_pthread_check_macro must be defined" -+# endif -+ static void routine(void *a) { a = 0; } -+ static void *start_routine(void *a) { return a; }], -+ [pthread_t th; pthread_attr_t attr; -+ pthread_create(&th, 0, start_routine, 0); -+ pthread_join(th, 0); -+ pthread_attr_init(&attr); -+ pthread_cleanup_push(routine, 0); -+ pthread_cleanup_pop(0) /* ; */])], -+ [ax_pthread_ok=yes], -+ []) -+ -+ CFLAGS="$ax_pthread_save_CFLAGS" -+ LIBS="$ax_pthread_save_LIBS" -+ -+ AC_MSG_RESULT([$ax_pthread_ok]) -+ AS_IF([test "x$ax_pthread_ok" = "xyes"], [break]) -+ -+ PTHREAD_LIBS="" -+ PTHREAD_CFLAGS="" -+done -+fi -+ -+# Various other checks: -+if test "x$ax_pthread_ok" = "xyes"; then -+ ax_pthread_save_CFLAGS="$CFLAGS" -+ ax_pthread_save_LIBS="$LIBS" -+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS" -+ LIBS="$PTHREAD_LIBS $LIBS" -+ -+ # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. -+ AC_CACHE_CHECK([for joinable pthread attribute], -+ [ax_cv_PTHREAD_JOINABLE_ATTR], -+ [ax_cv_PTHREAD_JOINABLE_ATTR=unknown -+ for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do -+ AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], -+ [int attr = $ax_pthread_attr; return attr /* ; */])], -+ [ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break], -+ []) -+ done -+ ]) -+ AS_IF([test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \ -+ test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \ -+ test "x$ax_pthread_joinable_attr_defined" != "xyes"], -+ [AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE], -+ [$ax_cv_PTHREAD_JOINABLE_ATTR], -+ [Define to necessary symbol if this constant -+ uses a non-standard name on your system.]) -+ ax_pthread_joinable_attr_defined=yes -+ ]) -+ -+ AC_CACHE_CHECK([whether more special flags are required for pthreads], -+ [ax_cv_PTHREAD_SPECIAL_FLAGS], -+ [ax_cv_PTHREAD_SPECIAL_FLAGS=no -+ case $host_os in -+ solaris*) -+ ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS" -+ ;; -+ esac -+ ]) -+ AS_IF([test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \ -+ test "x$ax_pthread_special_flags_added" != "xyes"], -+ [PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS" -+ ax_pthread_special_flags_added=yes]) -+ -+ AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT], -+ [ax_cv_PTHREAD_PRIO_INHERIT], -+ [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], -+ [[int i = PTHREAD_PRIO_INHERIT;]])], -+ [ax_cv_PTHREAD_PRIO_INHERIT=yes], -+ [ax_cv_PTHREAD_PRIO_INHERIT=no]) -+ ]) -+ AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \ -+ test "x$ax_pthread_prio_inherit_defined" != "xyes"], -+ [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.]) -+ ax_pthread_prio_inherit_defined=yes -+ ]) -+ -+ CFLAGS="$ax_pthread_save_CFLAGS" -+ LIBS="$ax_pthread_save_LIBS" -+ -+ # More AIX lossage: compile with *_r variant -+ if test "x$GCC" != "xyes"; then -+ case $host_os in -+ aix*) -+ AS_CASE(["x/$CC"], -+ [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6], -+ [#handle absolute path differently from PATH based program lookup -+ AS_CASE(["x$CC"], -+ [x/*], -+ [AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])], -+ [AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])]) -+ ;; -+ esac -+ fi -+fi -+ -+test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" -+ -+AC_SUBST([PTHREAD_LIBS]) -+AC_SUBST([PTHREAD_CFLAGS]) -+AC_SUBST([PTHREAD_CC]) -+ -+# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: -+if test "x$ax_pthread_ok" = "xyes"; then -+ ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1]) -+ : -+else -+ ax_pthread_ok=no -+ $2 -+fi -+AC_LANG_POP -+])dnl AX_PTHREAD -diff --git a/src/Makefile.am b/src/Makefile.am -index 5ced544..efd95eb 100644 ---- a/src/Makefile.am -+++ b/src/Makefile.am -@@ -1,7 +1,7 @@ - AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir) - --AM_CFLAGS = $(GLOBAL_CFLAGS) $(libusbmuxd_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(libplist_CFLAGS) $(LFS_CFLAGS) $(openssl_CFLAGS) --AM_LDFLAGS = $(libgnutls_LIBS) $(libtasn1_LIBS) $(libplist_LIBS) $(libusbmuxd_LIBS) $(libgcrypt_LIBS) $(libpthread_LIBS) $(openssl_LIBS) -+AM_CFLAGS = $(GLOBAL_CFLAGS) $(libusbmuxd_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(libplist_CFLAGS) $(LFS_CFLAGS) $(openssl_CFLAGS) $(PTHREAD_CFLAGS) -+AM_LDFLAGS = $(libgnutls_LIBS) $(libtasn1_LIBS) $(libplist_LIBS) $(libusbmuxd_LIBS) $(libgcrypt_LIBS) $(openssl_LIBS) $(PTHREAD_LIBS) - - lib_LTLIBRARIES = libimobiledevice.la - libimobiledevice_la_LIBADD = $(top_builddir)/common/libinternalcommon.la --- -2.14.1 - - -From b78a42e0531d219e27f5c57350886bc7c14d4684 Mon Sep 17 00:00:00 2001 -From: Nikias Bassen -Date: Wed, 4 Jan 2017 20:28:59 +0100 -Subject: [PATCH 50/65] ideviceprovision: Silence compiler warning (missing - parenthesis) - ---- - tools/ideviceprovision.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/tools/ideviceprovision.c b/tools/ideviceprovision.c -index db00702..0bef7e8 100644 ---- a/tools/ideviceprovision.c -+++ b/tools/ideviceprovision.c -@@ -156,7 +156,7 @@ static plist_t profile_get_embedded_plist(plist_t profile) - size_t slen = asn1_item_get_size(pp); - char bsize = *(pp+1); - if (bsize & 0x80) { -- slen += 2 + bsize & 0xF; -+ slen += 2 + (bsize & 0xF); - } else { - slen += 3; - } --- -2.14.1 - - -From 45fda819e1aae3cacf25a04b9fe22cd6ddc61f5a Mon Sep 17 00:00:00 2001 -From: Antoine Reversat -Date: Tue, 10 Jan 2017 09:55:15 -0800 -Subject: [PATCH 51/65] property_list_service: Remove packet length check when - receiving plist data - -There are services that would send really large plist data, e.g. when listing -provisioning profiles. Instead of forcing the data to be less than 16MB we -try to allocate a buffer as large as requested. If the allocation fails the -function returns with an error. ---- - src/property_list_service.c | 89 ++++++++++++++++++++++----------------------- - 1 file changed, 43 insertions(+), 46 deletions(-) - -diff --git a/src/property_list_service.c b/src/property_list_service.c -index 141fab7..a5bdf9b 100644 ---- a/src/property_list_service.c -+++ b/src/property_list_service.c -@@ -193,59 +193,56 @@ static property_list_service_error_t internal_plist_receive_timeout(property_lis - debug_info("initial read failed!"); - return PROPERTY_LIST_SERVICE_E_MUX_ERROR; - } else { -+ uint32_t curlen = 0; -+ char *content = NULL; -+ - pktlen = be32toh(pktlen); -- if (pktlen < (1 << 24)) { /* prevent huge buffers */ -- uint32_t curlen = 0; -- char *content = NULL; -- debug_info("%d bytes following", pktlen); -- content = (char*)malloc(pktlen); -- if (!content) { -- debug_info("out of memory when allocating %d bytes", pktlen); -- return PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR; -- } -+ debug_info("%d bytes following", pktlen); -+ content = (char*)malloc(pktlen); -+ if (!content) { -+ debug_info("out of memory when allocating %d bytes", pktlen); -+ return PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR; -+ } - -- while (curlen < pktlen) { -- service_receive(client->parent, content+curlen, pktlen-curlen, &bytes); -- if (bytes <= 0) { -- res = PROPERTY_LIST_SERVICE_E_MUX_ERROR; -- break; -- } -- debug_info("received %d bytes", bytes); -- curlen += bytes; -- } -- if (curlen < pktlen) { -- debug_info("received incomplete packet (%d of %d bytes)", curlen, pktlen); -- if (curlen > 0) { -- debug_info("incomplete packet following:"); -- debug_buffer(content, curlen); -- } -- free(content); -- return res; -+ while (curlen < pktlen) { -+ service_receive(client->parent, content+curlen, pktlen-curlen, &bytes); -+ if (bytes <= 0) { -+ res = PROPERTY_LIST_SERVICE_E_MUX_ERROR; -+ break; - } -- if ((pktlen > 8) && !memcmp(content, "bplist00", 8)) { -- plist_from_bin(content, pktlen, plist); -- } else if ((pktlen > 5) && !memcmp(content, "= 0) && (content[bytes] < 0x20) && (content[bytes] != 0x09) && (content[bytes] != 0x0a) && (content[bytes] != 0x0d)) -- content[bytes] = 0x20; -- } -- plist_from_xml(content, pktlen, plist); -- } else { -- debug_info("WARNING: received unexpected non-plist content"); -- debug_buffer(content, pktlen); -- } -- if (*plist) { -- debug_plist(*plist); -- res = PROPERTY_LIST_SERVICE_E_SUCCESS; -- } else { -- res = PROPERTY_LIST_SERVICE_E_PLIST_ERROR; -+ debug_info("received %d bytes", bytes); -+ curlen += bytes; -+ } -+ if (curlen < pktlen) { -+ debug_info("received incomplete packet (%d of %d bytes)", curlen, pktlen); -+ if (curlen > 0) { -+ debug_info("incomplete packet following:"); -+ debug_buffer(content, curlen); - } - free(content); -- content = NULL; -+ return res; -+ } -+ if ((pktlen > 8) && !memcmp(content, "bplist00", 8)) { -+ plist_from_bin(content, pktlen, plist); -+ } else if ((pktlen > 5) && !memcmp(content, "= 0) && (content[bytes] < 0x20) && (content[bytes] != 0x09) && (content[bytes] != 0x0a) && (content[bytes] != 0x0d)) -+ content[bytes] = 0x20; -+ } -+ plist_from_xml(content, pktlen, plist); -+ } else { -+ debug_info("WARNING: received unexpected non-plist content"); -+ debug_buffer(content, pktlen); -+ } -+ if (*plist) { -+ debug_plist(*plist); -+ res = PROPERTY_LIST_SERVICE_E_SUCCESS; - } else { -- res = PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR; -+ res = PROPERTY_LIST_SERVICE_E_PLIST_ERROR; - } -+ free(content); -+ content = NULL; - } - return res; - } --- -2.14.1 - - -From 5a8449a391d2cc848f55cfb4406bad4ded0bd138 Mon Sep 17 00:00:00 2001 -From: BALATON Zoltan -Date: Tue, 12 Jul 2016 23:01:47 +0200 -Subject: [PATCH 52/65] Propagate lower level errors to callers instead of - returning unknown error for most failures - ---- - include/libimobiledevice/lockdown.h | 2 +- - src/idevice.c | 4 +- - src/lockdown.c | 76 +++++++++++++++++++------------------ - src/property_list_service.c | 4 +- - 4 files changed, 46 insertions(+), 40 deletions(-) - -diff --git a/include/libimobiledevice/lockdown.h b/include/libimobiledevice/lockdown.h -index 0e48eef..b5c126c 100644 ---- a/include/libimobiledevice/lockdown.h -+++ b/include/libimobiledevice/lockdown.h -@@ -43,7 +43,7 @@ typedef enum { - LOCKDOWN_E_PAIRING_FAILED = -4, - LOCKDOWN_E_SSL_ERROR = -5, - LOCKDOWN_E_DICT_ERROR = -6, -- LOCKDOWN_E_NOT_ENOUGH_DATA = -7, -+ LOCKDOWN_E_RECEIVE_TIMEOUT = -7, - LOCKDOWN_E_MUX_ERROR = -8, - LOCKDOWN_E_NO_RUNNING_SESSION = -9, - /* native */ -diff --git a/src/idevice.c b/src/idevice.c -index b6dfe4e..913038e 100644 ---- a/src/idevice.c -+++ b/src/idevice.c -@@ -376,8 +376,8 @@ static idevice_error_t internal_connection_receive_timeout(idevice_connection_t - if (connection->type == CONNECTION_USBMUXD) { - int res = usbmuxd_recv_timeout((int)(long)connection->data, data, len, recv_bytes, timeout); - if (res < 0) { -- debug_info("ERROR: usbmuxd_recv_timeout returned %d (%s)", res, strerror(-res)); -- return IDEVICE_E_UNKNOWN_ERROR; -+ debug_info("ERROR: usbmuxd_recv_timeout returned %d (%s)", res, strerror(errno)); -+ return (res == -EAGAIN ? IDEVICE_E_NOT_ENOUGH_DATA : IDEVICE_E_UNKNOWN_ERROR); - } - return IDEVICE_E_SUCCESS; - } else { -diff --git a/src/lockdown.c b/src/lockdown.c -index cae950b..5251737 100644 ---- a/src/lockdown.c -+++ b/src/lockdown.c -@@ -135,6 +135,36 @@ static lockdownd_error_t lockdownd_strtoerr(const char* name) - return err; - } - -+/** -+ * Convert a property_list_service_error_t value to a lockdownd_error_t -+ * value. Used internally to get correct error codes. -+ * -+ * @param err A property_list_service_error_t error code -+ * -+ * @return A matching lockdownd_error_t error code, -+ * LOCKDOWND_E_UNKNOWN_ERROR otherwise. -+ */ -+static lockdownd_error_t lockdownd_error(property_list_service_error_t err) -+{ -+ switch (err) { -+ case PROPERTY_LIST_SERVICE_E_SUCCESS: -+ return LOCKDOWN_E_SUCCESS; -+ case PROPERTY_LIST_SERVICE_E_INVALID_ARG: -+ return LOCKDOWN_E_INVALID_ARG; -+ case PROPERTY_LIST_SERVICE_E_PLIST_ERROR: -+ return LOCKDOWN_E_PLIST_ERROR; -+ case PROPERTY_LIST_SERVICE_E_MUX_ERROR: -+ return LOCKDOWN_E_MUX_ERROR; -+ case PROPERTY_LIST_SERVICE_E_SSL_ERROR: -+ return LOCKDOWN_E_SSL_ERROR; -+ case PROPERTY_LIST_SERVICE_E_RECEIVE_TIMEOUT: -+ return LOCKDOWN_E_RECEIVE_TIMEOUT; -+ default: -+ break; -+ } -+ return LOCKDOWN_E_UNKNOWN_ERROR; -+} -+ - /** - * Internally used function for checking the result from lockdown's answer - * plist to a previously sent request. -@@ -349,18 +379,8 @@ LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_receive(lockdownd_client_t clie - { - if (!client || !plist || (plist && *plist)) - return LOCKDOWN_E_INVALID_ARG; -- lockdownd_error_t ret = LOCKDOWN_E_SUCCESS; -- property_list_service_error_t err; -- -- err = property_list_service_receive_plist(client->parent, plist); -- if (err != PROPERTY_LIST_SERVICE_E_SUCCESS) { -- ret = LOCKDOWN_E_UNKNOWN_ERROR; -- } - -- if (!*plist) -- ret = LOCKDOWN_E_PLIST_ERROR; -- -- return ret; -+ return lockdownd_error(property_list_service_receive_plist(client->parent, plist)); - } - - LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_send(lockdownd_client_t client, plist_t plist) -@@ -368,14 +388,7 @@ LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_send(lockdownd_client_t client, - if (!client || !plist) - return LOCKDOWN_E_INVALID_ARG; - -- lockdownd_error_t ret = LOCKDOWN_E_SUCCESS; -- property_list_service_error_t err; -- -- err = property_list_service_send_xml_plist(client->parent, plist); -- if (err != PROPERTY_LIST_SERVICE_E_SUCCESS) { -- ret = LOCKDOWN_E_UNKNOWN_ERROR; -- } -- return ret; -+ return lockdownd_error(property_list_service_send_xml_plist(client->parent, plist)); - } - - LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_query_type(lockdownd_client_t client, char **type) -@@ -686,13 +699,11 @@ LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_client_new_with_handshake(idevi - } - - /* perform handshake */ -- if (LOCKDOWN_E_SUCCESS != lockdownd_query_type(client_loc, &type)) { -+ ret = lockdownd_query_type(client_loc, &type); -+ if (LOCKDOWN_E_SUCCESS != ret) { - debug_info("QueryType failed in the lockdownd client."); -- ret = LOCKDOWN_E_NOT_ENOUGH_DATA; -- } else { -- if (strcmp("com.apple.mobile.lockdown", type)) { -- debug_info("Warning QueryType request returned \"%s\".", type); -- } -+ } else if (strcmp("com.apple.mobile.lockdown", type)) { -+ debug_info("Warning QueryType request returned \"%s\".", type); - } - free(type); - -@@ -1113,7 +1124,6 @@ LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_goodbye(lockdownd_client_t clie - LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_start_session(lockdownd_client_t client, const char *host_id, char **session_id, int *ssl_enabled) - { - lockdownd_error_t ret = LOCKDOWN_E_SUCCESS; -- property_list_service_error_t plret; - plist_t dict = NULL; - - if (!client || !host_id) -@@ -1184,20 +1194,14 @@ LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_start_session(lockdownd_client_ - debug_info("Failed to get SessionID!"); - } - -- debug_info("Enable SSL Session: %s", (use_ssl?"true":"false")); -+ debug_info("Enable SSL Session: %s", (use_ssl ? "true" : "false")); - - if (use_ssl) { -- plret = property_list_service_enable_ssl(client->parent); -- if (plret == PROPERTY_LIST_SERVICE_E_SUCCESS) { -- ret = LOCKDOWN_E_SUCCESS; -- client->ssl_enabled = 1; -- } else { -- ret = LOCKDOWN_E_SSL_ERROR; -- client->ssl_enabled = 0; -- } -+ ret = lockdownd_error(property_list_service_enable_ssl(client->parent)); -+ client->ssl_enabled = (ret == LOCKDOWN_E_SUCCESS ? 1 : 0); - } else { -- client->ssl_enabled = 0; - ret = LOCKDOWN_E_SUCCESS; -+ client->ssl_enabled = 0; - } - } - -diff --git a/src/property_list_service.c b/src/property_list_service.c -index a5bdf9b..f411699 100644 ---- a/src/property_list_service.c -+++ b/src/property_list_service.c -@@ -98,7 +98,8 @@ LIBIMOBILEDEVICE_API property_list_service_error_t property_list_service_client_ - * @return PROPERTY_LIST_SERVICE_E_SUCCESS on success, - * PROPERTY_LIST_SERVICE_E_INVALID_ARG when one or more parameters are - * invalid, PROPERTY_LIST_SERVICE_E_PLIST_ERROR when dict is not a valid -- * plist, or PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR when an unspecified -+ * plist, PROPERTY_LIST_SERVICE_E_MUX_ERROR when a communication error -+ * occurs, or PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR when an unspecified - * error occurs. - */ - static property_list_service_error_t internal_plist_send(property_list_service_client_t client, plist_t plist, int binary) -@@ -140,6 +141,7 @@ static property_list_service_error_t internal_plist_send(property_list_service_c - } - if (bytes <= 0) { - debug_info("ERROR: sending to device failed."); -+ res = PROPERTY_LIST_SERVICE_E_MUX_ERROR; - } - - free(content); --- -2.14.1 - - -From 4bdea2983a3204332b09408c62e440a0b8e23605 Mon Sep 17 00:00:00 2001 -From: BALATON Zoltan -Date: Tue, 7 Feb 2017 17:13:22 +0100 -Subject: [PATCH 53/65] Added IDEVICE_DEVICE_PAIRED event constant matching the - corresponding event number in libusbmuxd - ---- - include/libimobiledevice/libimobiledevice.h | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/include/libimobiledevice/libimobiledevice.h b/include/libimobiledevice/libimobiledevice.h -index b125adf..68eb511 100644 ---- a/include/libimobiledevice/libimobiledevice.h -+++ b/include/libimobiledevice/libimobiledevice.h -@@ -55,7 +55,8 @@ typedef idevice_connection_private *idevice_connection_t; /**< The connection ha - /** The event type for device add or removal */ - enum idevice_event_type { - IDEVICE_DEVICE_ADD = 1, -- IDEVICE_DEVICE_REMOVE -+ IDEVICE_DEVICE_REMOVE, -+ IDEVICE_DEVICE_PAIRED - }; - - /* event data structure */ --- -2.14.1 - - -From f8999ef550fe9a97b24f4bbb17b66f186a5deae1 Mon Sep 17 00:00:00 2001 -From: BALATON Zoltan -Date: Tue, 7 Feb 2017 17:15:46 +0100 -Subject: [PATCH 54/65] Define htobe16 if not defined - ---- - include/endianness.h | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/include/endianness.h b/include/endianness.h -index 585e768..2d6ad0e 100644 ---- a/include/endianness.h -+++ b/include/endianness.h -@@ -27,6 +27,10 @@ - #endif - #endif - -+#ifndef htobe16 -+#define htobe16 be16toh -+#endif -+ - #ifndef __bswap_32 - #define __bswap_32(x) ((((x) & 0xFF000000) >> 24) \ - | (((x) & 0x00FF0000) >> 8) \ --- -2.14.1 - - -From 1d844aae7820d10abf9a19b7acfb88341ac6e961 Mon Sep 17 00:00:00 2001 -From: BALATON Zoltan -Date: Tue, 7 Feb 2017 17:17:03 +0100 -Subject: [PATCH 55/65] Fix parameter check of - instproxy_check_capabilities_match() - -The capabilities parameter is a string array not a plist. Also check -other parameters when we are at it. ---- - src/installation_proxy.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/installation_proxy.c b/src/installation_proxy.c -index 9f367aa..f82eecc 100644 ---- a/src/installation_proxy.c -+++ b/src/installation_proxy.c -@@ -772,7 +772,7 @@ LIBIMOBILEDEVICE_API instproxy_error_t instproxy_remove_archive(instproxy_client - - LIBIMOBILEDEVICE_API instproxy_error_t instproxy_check_capabilities_match(instproxy_client_t client, const char** capabilities, plist_t client_options, plist_t *result) - { -- if (!capabilities || (plist_get_node_type(capabilities) != PLIST_ARRAY && plist_get_node_type(capabilities) != PLIST_DICT)) -+ if (!client || !capabilities || !result) - return INSTPROXY_E_INVALID_ARG; - - plist_t lookup_result = NULL; --- -2.14.1 - - -From 02a0e03e24bc96bba2e5ea2438c30baf803fd137 Mon Sep 17 00:00:00 2001 -From: Christophe Fergeau -Date: Tue, 25 Apr 2017 14:09:48 +0200 -Subject: [PATCH 56/65] Avoid double free with OpenSSL 1.1.0 - -Since commit OpenSSL_1_1_0-pre3~178 -https://github.com/openssl/openssl/commit/b184e3ef73200cb3b7914a603b43a5b8a074c85f -OpenSSL automatically cleans up some of its internal data when the -program exits. This conflicts with some similar clean up -libimobiledevice attempts to do, which causes a double-free. -SSL_COMP_free_compression_methods() was available in OpenSSL 1.0.2, -and is still there in 1.1.0 as a no-op, so we can use that to free -the compression methods. - -This bug can be hit with a simple idevicebackup2 --help - -==14299== Invalid read of size 4 -==14299== at 0x547AEBC: OPENSSL_sk_pop_free (stack.c:263) -==14299== by 0x508B848: ssl_library_stop (ssl_init.c:182) -==14299== by 0x5424D11: OPENSSL_cleanup (init.c:402) -==14299== by 0x5DC3134: __cxa_finalize (cxa_finalize.c:56) -==14299== by 0x53332B2: ??? (in /usr/lib64/libcrypto.so.1.1.0e) -==14299== by 0x4011232: _dl_fini (dl-fini.c:235) -==14299== by 0x5DC2DC7: __run_exit_handlers (exit.c:83) -==14299== by 0x5DC2E19: exit (exit.c:105) -==14299== by 0x5DA8604: (below main) (libc-start.c:329) -==14299== Address 0x6585590 is 0 bytes inside a block of size 40 free'd -==14299== at 0x4C2FCC8: free (vg_replace_malloc.c:530) -==14299== by 0x4E43381: sk_SSL_COMP_free (ssl.h:830) -==14299== by 0x4E434E7: internal_idevice_deinit (idevice.c:103) -==14299== by 0x5B79643: __pthread_once_slow (pthread_once.c:116) -==14299== by 0x4E5663A: thread_once (thread.c:104) -==14299== by 0x4E43525: libimobiledevice_deinitialize (idevice.c:140) -==14299== by 0x4011232: _dl_fini (dl-fini.c:235) -==14299== by 0x5DC2DC7: __run_exit_handlers (exit.c:83) -==14299== by 0x5DC2E19: exit (exit.c:105) -==14299== by 0x5DA8604: (below main) (libc-start.c:329) -==14299== Block was alloc'd at -==14299== at 0x4C2EB1B: malloc (vg_replace_malloc.c:299) -==14299== by 0x5428908: CRYPTO_zalloc (mem.c:100) -==14299== by 0x547A9AE: OPENSSL_sk_new (stack.c:108) -==14299== by 0x5087D43: sk_SSL_COMP_new (ssl.h:830) -==14299== by 0x5087D43: do_load_builtin_compressions (ssl_ciph.c:482) -==14299== by 0x5087D43: do_load_builtin_compressions_ossl_ (ssl_ciph.c:476) -==14299== by 0x5B79643: __pthread_once_slow (pthread_once.c:116) -==14299== by 0x547B198: CRYPTO_THREAD_run_once (threads_pthread.c:106) -==14299== by 0x5089F96: load_builtin_compressions (ssl_ciph.c:500) -==14299== by 0x5089F96: SSL_COMP_get_compression_methods (ssl_ciph.c:1845) -==14299== by 0x508B68B: ossl_init_ssl_base (ssl_init.c:125) -==14299== by 0x508B68B: ossl_init_ssl_base_ossl_ (ssl_init.c:25) -==14299== by 0x5B79643: __pthread_once_slow (pthread_once.c:116) -==14299== by 0x547B198: CRYPTO_THREAD_run_once (threads_pthread.c:106) -==14299== by 0x508B90A: OPENSSL_init_ssl (ssl_init.c:227) -==14299== by 0x4E43416: internal_idevice_init (idevice.c:73) -= - -Signed-off-by: Christophe Fergeau ---- - src/idevice.c | 10 +++++++++- - 1 file changed, 9 insertions(+), 1 deletion(-) - -diff --git a/src/idevice.c b/src/idevice.c -index 913038e..d1f13cb 100644 ---- a/src/idevice.c -+++ b/src/idevice.c -@@ -51,6 +51,14 @@ - #include "common/debug.h" - - #ifdef HAVE_OPENSSL -+ -+#if OPENSSL_VERSION_NUMBER < 0x10002000L -+static void SSL_COMP_free_compression_methods(void) -+{ -+ sk_SSL_COMP_free(SSL_COMP_get_compression_methods()); -+} -+#endif -+ - static mutex_t *mutex_buf = NULL; - static void locking_function(int mode, int n, const char* file, int line) - { -@@ -100,7 +108,7 @@ static void internal_idevice_deinit(void) - - EVP_cleanup(); - CRYPTO_cleanup_all_ex_data(); -- sk_SSL_COMP_free(SSL_COMP_get_compression_methods()); -+ SSL_COMP_free_compression_methods(); - #ifdef HAVE_ERR_REMOVE_THREAD_STATE - ERR_remove_thread_state(NULL); - #else --- -2.14.1 - - -From f635812ccc9b2eb63f5bc2b494d7fdae9c9e1ef3 Mon Sep 17 00:00:00 2001 -From: Christophe Fergeau -Date: Wed, 26 Apr 2017 11:36:54 +0200 -Subject: [PATCH 57/65] Don't use ERR_remove_thread_state() with OpenSSL 1.1.0 - -It's deprecated and causes compile-time warnings. We don't want to -fallback to ERR_remove_state() either as it's similarly deprecated. - -This commit adds a helper functions to hide the #ifdef mess between -the various openssl versions. - -Signed-off-by: Christophe Fergeau ---- - src/idevice.c | 30 ++++++++++++++++-------------- - 1 file changed, 16 insertions(+), 14 deletions(-) - -diff --git a/src/idevice.c b/src/idevice.c -index d1f13cb..1c43269 100644 ---- a/src/idevice.c -+++ b/src/idevice.c -@@ -37,10 +37,7 @@ - #ifdef HAVE_OPENSSL - #include - #include --#if OPENSSL_VERSION_NUMBER >= 0x10000001L --/* since OpenSSL 1.0.0-beta1 */ --#define HAVE_ERR_REMOVE_THREAD_STATE 1 --#endif -+ - #else - #include - #endif -@@ -59,6 +56,19 @@ static void SSL_COMP_free_compression_methods(void) - } - #endif - -+static void openssl_remove_thread_state(void) -+{ -+/* ERR_remove_thread_state() is available since OpenSSL 1.0.0-beta1, but -+ * deprecated in OpenSSL 1.1.0 */ -+#if OPENSSL_VERSION_NUMBER < 0x10100000L -+#if OPENSSL_VERSION_NUMBER >= 0x10000001L -+ ERR_remove_thread_state(NULL); -+#else -+ ERR_remove_state(0); -+#endif -+#endif -+} -+ - static mutex_t *mutex_buf = NULL; - static void locking_function(int mode, int n, const char* file, int line) - { -@@ -109,11 +119,7 @@ static void internal_idevice_deinit(void) - EVP_cleanup(); - CRYPTO_cleanup_all_ex_data(); - SSL_COMP_free_compression_methods(); --#ifdef HAVE_ERR_REMOVE_THREAD_STATE -- ERR_remove_thread_state(NULL); --#else -- ERR_remove_state(0); --#endif -+ openssl_remove_thread_state(); - #else - gnutls_global_deinit(); - #endif -@@ -764,11 +770,7 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_enable_ssl(idevice_conne - debug_info("SSL mode enabled, cipher: %s", SSL_get_cipher(ssl)); - } - /* required for proper multi-thread clean up to prevent leaks */ --#ifdef HAVE_ERR_REMOVE_THREAD_STATE -- ERR_remove_thread_state(NULL); --#else -- ERR_remove_state(0); --#endif -+ openssl_remove_thread_state(); - #else - ssl_data_t ssl_data_loc = (ssl_data_t)malloc(sizeof(struct ssl_data_private)); - --- -2.14.1 - - -From b89e4823ef9528936072f5f195d7fdab9e1f838b Mon Sep 17 00:00:00 2001 -From: Christophe Fergeau -Date: Tue, 25 Apr 2017 16:59:15 +0200 -Subject: [PATCH 58/65] #ifdef out code which is a no-op with OpenSSL 1.1.0 - -CRYPTO_set_id_callback -CRYPTO_set_locking_callback -EVP_cleanup -CRYPTO_cleanup_all_ex_data -SSL_COMP_free_compression_methods - -are all no-ops with OpenSSL 1.1.0, so we can #ifdef out the -corresponding code. This cleans up some warnings about -id_function/locking_function being defined but unused (as the calls to -CRYPTO_set_id_callback and CRYPTO_set_locking_callback disappear at -preprocessing time). - -Signed-off-by: Christophe Fergeau ---- - src/idevice.c | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/src/idevice.c b/src/idevice.c -index 1c43269..89724ff 100644 ---- a/src/idevice.c -+++ b/src/idevice.c -@@ -69,6 +69,7 @@ static void openssl_remove_thread_state(void) - #endif - } - -+#if OPENSSL_VERSION_NUMBER < 0x10100000L - static mutex_t *mutex_buf = NULL; - static void locking_function(int mode, int n, const char* file, int line) - { -@@ -83,10 +84,12 @@ static unsigned long id_function(void) - return ((unsigned long)THREAD_ID); - } - #endif -+#endif - - static void internal_idevice_init(void) - { - #ifdef HAVE_OPENSSL -+#if OPENSSL_VERSION_NUMBER < 0x10100000L - int i; - SSL_library_init(); - -@@ -98,6 +101,7 @@ static void internal_idevice_init(void) - - CRYPTO_set_id_callback(id_function); - CRYPTO_set_locking_callback(locking_function); -+#endif - #else - gnutls_global_init(); - #endif -@@ -106,6 +110,7 @@ static void internal_idevice_init(void) - static void internal_idevice_deinit(void) - { - #ifdef HAVE_OPENSSL -+#if OPENSSL_VERSION_NUMBER < 0x10100000L - int i; - if (mutex_buf) { - CRYPTO_set_id_callback(NULL); -@@ -120,6 +125,7 @@ static void internal_idevice_deinit(void) - CRYPTO_cleanup_all_ex_data(); - SSL_COMP_free_compression_methods(); - openssl_remove_thread_state(); -+#endif - #else - gnutls_global_deinit(); - #endif --- -2.14.1 - - -From a5b2266b4e9c2112f85f94aa1d45440007922e08 Mon Sep 17 00:00:00 2001 -From: Nikias Bassen -Date: Thu, 27 Apr 2017 14:32:49 +0200 -Subject: [PATCH 59/65] cython: Fix build error after error constant rename - ---- - cython/lockdown.pxi | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/cython/lockdown.pxi b/cython/lockdown.pxi -index c8d511e..f249049 100644 ---- a/cython/lockdown.pxi -+++ b/cython/lockdown.pxi -@@ -7,7 +7,7 @@ cdef extern from "libimobiledevice/lockdown.h": - LOCKDOWN_E_PAIRING_FAILED - LOCKDOWN_E_SSL_ERROR - LOCKDOWN_E_DICT_ERROR -- LOCKDOWN_E_NOT_ENOUGH_DATA -+ LOCKDOWN_E_RECEIVE_TIMEOUT - LOCKDOWN_E_SET_VALUE_PROHIBITED - LOCKDOWN_E_GET_VALUE_PROHIBITED - LOCKDOWN_E_MUX_ERROR -@@ -78,7 +78,7 @@ cdef class LockdownError(BaseError): - LOCKDOWN_E_PAIRING_FAILED: "Pairing failed", - LOCKDOWN_E_SSL_ERROR: "SSL error", - LOCKDOWN_E_DICT_ERROR: "Dictionary error", -- LOCKDOWN_E_NOT_ENOUGH_DATA: "Not enough data", -+ LOCKDOWN_E_RECEIVE_TIMEOUT: "Receive timeout", - LOCKDOWN_E_MUX_ERROR: "Mux Protocol Error", - LOCKDOWN_E_NO_RUNNING_SESSION: "No running session", - LOCKDOWN_E_INVALID_RESPONSE: "Invalid response", --- -2.14.1 - - -From 0cf6bb6f5bece0885c6e4806b5e62ec4296ab75e Mon Sep 17 00:00:00 2001 -From: Nikos Mavrogiannopoulos -Date: Mon, 2 Jan 2017 14:35:39 +0100 -Subject: [PATCH 60/65] gnutls: check for interrupted gnutls_handshake() - -That is, recover if gnutls_handshake() returns with non fatal -error codes like GNUTLS_E_INTERRUPTED or GNUTLS_E_AGAIN. ---- - src/idevice.c | 13 ++++++++++--- - 1 file changed, 10 insertions(+), 3 deletions(-) - -diff --git a/src/idevice.c b/src/idevice.c -index 89724ff..21b10ba 100644 ---- a/src/idevice.c -+++ b/src/idevice.c -@@ -697,7 +697,11 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_enable_ssl(idevice_conne - return IDEVICE_E_INVALID_ARG; - - idevice_error_t ret = IDEVICE_E_SSL_ERROR; -+#ifdef HAVE_OPENSSL - uint32_t return_me = 0; -+#else -+ int return_me = 0; -+#endif - plist_t pair_record = NULL; - - userpref_read_pair_record(connection->udid, &pair_record); -@@ -817,14 +821,17 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_enable_ssl(idevice_conne - if (errno) { - debug_info("WARNING: errno says %s before handshake!", strerror(errno)); - } -- return_me = gnutls_handshake(ssl_data_loc->session); -+ -+ do { -+ return_me = gnutls_handshake(ssl_data_loc->session); -+ } while(return_me == GNUTLS_E_AGAIN || return_me == GNUTLS_E_INTERRUPTED); -+ - debug_info("GnuTLS handshake done..."); - - if (return_me != GNUTLS_E_SUCCESS) { - internal_ssl_cleanup(ssl_data_loc); - free(ssl_data_loc); -- debug_info("GnuTLS reported something wrong."); -- gnutls_perror(return_me); -+ debug_info("GnuTLS reported something wrong: %s", gnutls_strerror(return_me)); - debug_info("oh.. errno says %s", strerror(errno)); - } else { - connection->ssl_data = ssl_data_loc; --- -2.14.1 - - -From 53fede06af98e24e26939127fcc71c6acfaf4c12 Mon Sep 17 00:00:00 2001 -From: Nikias Bassen -Date: Fri, 28 Apr 2017 20:58:53 +0200 -Subject: [PATCH 61/65] Updated README with some notes about configuration - options - ---- - README | 18 ++++++++++++++---- - 1 file changed, 14 insertions(+), 4 deletions(-) - -diff --git a/README b/README -index 972cfa8..efc09c0 100644 ---- a/README -+++ b/README -@@ -8,7 +8,7 @@ Requirements - ============ - - Development Packages of: -- libgnutls or openssl -+ OpenSSL or GnuTLS - libplist - libusbmuxd - -@@ -20,7 +20,7 @@ Software: - autoconf - libtool - pkg-config -- gcc -+ gcc or clang - - Optional: - cython (Python bindings) -@@ -34,6 +34,16 @@ To compile run: - make - sudo make install - -+If you require a custom prefix or other option being passed to ./configure -+you can pass them directly to ./autogen.sh like this: -+ ./autogen.sh --prefix=/opt/local --enable-debug-code -+ make -+ sudo make install -+ -+By default, OpenSSL will be used. If you prefer GnuTLS, configure with -+ --disable-openssl like this: -+ ./autogen.sh --disable-openssl -+ - Who/What/Where? - =============== - -@@ -47,7 +57,7 @@ Code (Mirror): - git clone https://github.com/libimobiledevice/libimobiledevice.git - - Tickets: -- http://github.com/libimobiledevice/libimobiledevice/issues -+ https://github.com/libimobiledevice/libimobiledevice/issues - - Mailing List: - http://lists.libimobiledevice.org/mailman/listinfo/libimobiledevice-devel -@@ -66,4 +76,4 @@ libimobiledevice is an independent software library and has not been - authorized, sponsored, or otherwise approved by Apple Inc. - - README Updated on: -- 2015-01-28 -+ 2017-04-28 --- -2.14.1 - - -From 835d84b678d23f92622445f5bf142c2bf52a7e9b Mon Sep 17 00:00:00 2001 -From: Nikias Bassen -Date: Sun, 18 Jun 2017 04:10:57 +0200 -Subject: [PATCH 62/65] idevicescreenshot: Detect screenshot image format to - determine file extension - ---- - tools/idevicescreenshot.c | 20 +++++++++++++++----- - 1 file changed, 15 insertions(+), 5 deletions(-) - -diff --git a/tools/idevicescreenshot.c b/tools/idevicescreenshot.c -index da229e2..74acdf6 100644 ---- a/tools/idevicescreenshot.c -+++ b/tools/idevicescreenshot.c -@@ -99,12 +99,22 @@ int main(int argc, char **argv) - } else { - char *imgdata = NULL; - uint64_t imgsize = 0; -- if (!filename) { -- time_t now = time(NULL); -- filename = (char*)malloc(36); -- strftime(filename, 36, "screenshot-%Y-%m-%d-%H-%M-%S.tiff", gmtime(&now)); -- } - if (screenshotr_take_screenshot(shotr, &imgdata, &imgsize) == SCREENSHOTR_E_SUCCESS) { -+ if (!filename) { -+ const char *fileext = NULL; -+ if (memcmp(imgdata, "\x89PNG", 4) == 0) { -+ fileext = ".png"; -+ } else if (memcmp(imgdata, "MM\x00*", 4) == 0) { -+ fileext = ".tiff"; -+ } else { -+ printf("WARNING: screenshot data has unexpected image format.\n"); -+ fileext = ".dat"; -+ } -+ time_t now = time(NULL); -+ filename = (char*)malloc(36); -+ size_t pos = strftime(filename, 36, "screenshot-%Y-%m-%d-%H-%M-%S", gmtime(&now)); -+ sprintf(filename+pos, "%s", fileext); -+ } - FILE *f = fopen(filename, "wb"); - if (f) { - if (fwrite(imgdata, 1, (size_t)imgsize, f) == (size_t)imgsize) { --- -2.14.1 - - -From 5250024b53b799a427a486ae133ecb927f5c555e Mon Sep 17 00:00:00 2001 -From: Nikias Bassen -Date: Sat, 2 Jul 2016 01:37:50 +0200 -Subject: [PATCH 63/65] Add basic mobileactivation service implementation - ---- - include/Makefile.am | 1 + - include/libimobiledevice/mobileactivation.h | 144 +++++++++++++++++++ - src/Makefile.am | 1 + - src/mobileactivation.c | 209 ++++++++++++++++++++++++++++ - src/mobileactivation.h | 32 +++++ - 5 files changed, 387 insertions(+) - create mode 100644 include/libimobiledevice/mobileactivation.h - create mode 100644 src/mobileactivation.c - create mode 100644 src/mobileactivation.h - -diff --git a/include/Makefile.am b/include/Makefile.am -index 9f61e6b..f2b93ed 100644 ---- a/include/Makefile.am -+++ b/include/Makefile.am -@@ -20,5 +20,6 @@ nobase_include_HEADERS = libimobiledevice/libimobiledevice.h \ - libimobiledevice/diagnostics_relay.h\ - libimobiledevice/debugserver.h\ - libimobiledevice/syslog_relay.h\ -+ libimobiledevice/mobileactivation.h\ - libimobiledevice/property_list_service.h\ - libimobiledevice/service.h -diff --git a/include/libimobiledevice/mobileactivation.h b/include/libimobiledevice/mobileactivation.h -new file mode 100644 -index 0000000..bb977fe ---- /dev/null -+++ b/include/libimobiledevice/mobileactivation.h -@@ -0,0 +1,144 @@ -+/** -+ * @file libimobiledevice/mobileactivation.h -+ * @brief Handle device activation and deactivation. -+ * \internal -+ * -+ * Copyright (c) 2016 Nikias Bassen, All Rights Reserved. -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -+ */ -+ -+#ifndef IMOBILEACTIVATION_H -+#define IMOBILEACTIVATION_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+#define MOBILEACTIVATION_SERVICE_NAME "com.apple.mobileactivationd" -+ -+/** Error Codes */ -+typedef enum { -+ MOBILEACTIVATION_E_SUCCESS = 0, -+ MOBILEACTIVATION_E_INVALID_ARG = -1, -+ MOBILEACTIVATION_E_PLIST_ERROR = -2, -+ MOBILEACTIVATION_E_MUX_ERROR = -3, -+ MOBILEACTIVATION_E_UNKNOWN_REQUEST = -4, -+ MOBILEACTIVATION_E_REQUEST_FAILED = -5, -+ MOBILEACTIVATION_E_UNKNOWN_ERROR = -256 -+} mobileactivation_error_t; -+ -+typedef struct mobileactivation_client_private mobileactivation_client_private; -+typedef mobileactivation_client_private *mobileactivation_client_t; /**< The client handle. */ -+ -+/** -+ * Connects to the mobileactivation service on the specified device. -+ * -+ * @param device The device to connect to. -+ * @param service The service descriptor returned by lockdownd_start_service. -+ * @param client Reference that will point to a newly allocated -+ * mobileactivation_client_t upon successful return. -+ * -+ * @return MOBILEACTIVATION_E_SUCCESS on success, -+ * MOBILEACTIVATION_E_INVALID_ARG when one of the parameters is invalid, -+ * or MOBILEACTIVATION_E_MUX_ERROR when the connection failed. -+ */ -+mobileactivation_error_t mobileactivation_client_new(idevice_t device, lockdownd_service_descriptor_t service, mobileactivation_client_t *client); -+ -+/** -+ * Starts a new mobileactivation service on the specified device and connects to it. -+ * -+ * @param device The device to connect to. -+ * @param client Pointer that will point to a newly allocated -+ * mobileactivation_client_t upon successful return. Must be freed using -+ * mobileactivation_client_free() after use. -+ * @param label The label to use for communication. Usually the program name. -+ * Pass NULL to disable sending the label in requests to lockdownd. -+ * -+ * @return MOBILEACTIVATION_E_SUCCESS on success, or an MOBILEACTIVATION_E_* -+ * error code otherwise. -+ */ -+mobileactivation_error_t mobileactivation_client_start_service(idevice_t device, mobileactivation_client_t* client, const char* label); -+ -+/** -+ * Disconnects a mobileactivation client from the device and frees up the -+ * mobileactivation client data. -+ * -+ * @param client The mobileactivation client to disconnect and free. -+ * -+ * @return MOBILEACTIVATION_E_SUCCESS on success, -+ * MOBILEACTIVATION_E_INVALID_ARG when one of client or client->parent -+ * is invalid, or MOBILEACTIVATION_E_UNKNOWN_ERROR when the was an -+ * error freeing the parent property_list_service client. -+ */ -+mobileactivation_error_t mobileactivation_client_free(mobileactivation_client_t client); -+ -+ -+/** -+ * Retrieves the device's activation state. -+ * -+ * @param client The mobileactivation client. -+ * @param state Pointer to a plist_t variable that will be set to the -+ * activation state reported by the mobileactivation service. The -+ * consumer is responsible for freeing the returned object using -+ * plist_free(). -+ * -+ * @return MOBILEACTIVATION_E_SUCCESS on success, or an MOBILEACTIVATION_E_* -+ * error code otherwise. -+ */ -+mobileactivation_error_t mobileactivation_get_activation_state(mobileactivation_client_t client, plist_t *state); -+ -+/** -+ * Retrieves the activation info required for device activation. -+ * -+ * @param client The mobileactivation client -+ * @param info Pointer to a plist_t variable that will be set to the -+ * activation info created by the mobileactivation service. The -+ * consumer is responsible for freeing the returned object using -+ * plist_free(). -+ * -+ * @return MOBILEACTIVATION_E_SUCCESS on success, or an MOBILEACTIVATION_E_* -+ * error code otherwise. -+ */ -+mobileactivation_error_t mobileactivation_create_activation_info(mobileactivation_client_t client, plist_t *info); -+ -+/** -+ * Activates the device with the given activation record. -+ * The activation record plist dictionary must be obtained using the -+ * activation protocol requesting from Apple's https webservice. -+ * -+ * @param client The mobileactivation client -+ * @param activation_record The activation record plist dictionary -+ * -+ * @return MOBILEACTIVATION_E_SUCCESS on success, or an MOBILEACTIVATION_E_* -+ * error code otherwise. -+ */ -+mobileactivation_error_t mobileactivation_activate(mobileactivation_client_t client, plist_t activation_record); -+ -+/** -+ * Deactivates the device. -+ * -+ * @param client The mobileactivation client -+ */ -+mobileactivation_error_t mobileactivation_deactivate(mobileactivation_client_t client); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif -diff --git a/src/Makefile.am b/src/Makefile.am -index efd95eb..fcde8ae 100644 ---- a/src/Makefile.am -+++ b/src/Makefile.am -@@ -28,6 +28,7 @@ libimobiledevice_la_SOURCES = idevice.c idevice.h \ - heartbeat.c heartbeat.h\ - debugserver.c debugserver.h\ - webinspector.c webinspector.h\ -+ mobileactivation.c mobileactivation.h\ - syslog_relay.c syslog_relay.h - - if WIN32 -diff --git a/src/mobileactivation.c b/src/mobileactivation.c -new file mode 100644 -index 0000000..f14eb73 ---- /dev/null -+++ b/src/mobileactivation.c -@@ -0,0 +1,209 @@ -+/* -+ * mobileactivation.c -+ * com.apple.mobileactivationd service implementation. -+ * -+ * Copyright (c) 2016 Nikias Bassen, All Rights Reserved. -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -+ */ -+#include -+#include -+#include "mobileactivation.h" -+#include "property_list_service.h" -+#include "common/debug.h" -+ -+/** -+ * Convert a property_list_service_error_t value to a mobileactivation_error_t value. -+ * Used internally to get correct error codes. -+ * -+ * @param err An property_list_service_error_t error code -+ * -+ * @return A matching mobileactivation_error_t error code, -+ * MOBILEACTIVATION_E_UNKNOWN_ERROR otherwise. -+ */ -+static mobileactivation_error_t mobileactivation_error(property_list_service_error_t err) -+{ -+ switch (err) { -+ case PROPERTY_LIST_SERVICE_E_SUCCESS: -+ return MOBILEACTIVATION_E_SUCCESS; -+ case PROPERTY_LIST_SERVICE_E_INVALID_ARG: -+ return MOBILEACTIVATION_E_INVALID_ARG; -+ case PROPERTY_LIST_SERVICE_E_PLIST_ERROR: -+ return MOBILEACTIVATION_E_PLIST_ERROR; -+ case PROPERTY_LIST_SERVICE_E_MUX_ERROR: -+ return MOBILEACTIVATION_E_MUX_ERROR; -+ default: -+ break; -+ } -+ return MOBILEACTIVATION_E_UNKNOWN_ERROR; -+} -+ -+LIBIMOBILEDEVICE_API mobileactivation_error_t mobileactivation_client_new(idevice_t device, lockdownd_service_descriptor_t service, mobileactivation_client_t *client) -+{ -+ if (!device || !service || service->port == 0 || !client || *client) { -+ return MOBILEACTIVATION_E_INVALID_ARG; -+ } -+ -+ property_list_service_client_t plistclient = NULL; -+ if (property_list_service_client_new(device, service, &plistclient) != PROPERTY_LIST_SERVICE_E_SUCCESS) { -+ return MOBILEACTIVATION_E_MUX_ERROR; -+ } -+ -+ /* create client object */ -+ mobileactivation_client_t client_loc = (mobileactivation_client_t) malloc(sizeof(struct mobileactivation_client_private)); -+ client_loc->parent = plistclient; -+ -+ /* all done, return success */ -+ *client = client_loc; -+ return MOBILEACTIVATION_E_SUCCESS; -+} -+ -+LIBIMOBILEDEVICE_API mobileactivation_error_t mobileactivation_client_start_service(idevice_t device, mobileactivation_client_t * client, const char* label) -+{ -+ mobileactivation_error_t err = MOBILEACTIVATION_E_UNKNOWN_ERROR; -+ service_client_factory_start_service(device, MOBILEACTIVATION_SERVICE_NAME, (void**)client, label, SERVICE_CONSTRUCTOR(mobileactivation_client_new), &err); -+ return err; -+} -+ -+LIBIMOBILEDEVICE_API mobileactivation_error_t mobileactivation_client_free(mobileactivation_client_t client) -+{ -+ if (!client) -+ return MOBILEACTIVATION_E_INVALID_ARG; -+ -+ if (property_list_service_client_free(client->parent) != PROPERTY_LIST_SERVICE_E_SUCCESS) { -+ return MOBILEACTIVATION_E_UNKNOWN_ERROR; -+ } -+ free(client); -+ return MOBILEACTIVATION_E_SUCCESS; -+} -+ -+static mobileactivation_error_t mobileactivation_check_result(plist_t dict, const char *command) -+{ -+ mobileactivation_error_t ret = MOBILEACTIVATION_E_UNKNOWN_ERROR; -+ -+ if (!dict || plist_get_node_type(dict) != PLIST_DICT) { -+ return MOBILEACTIVATION_E_PLIST_ERROR; -+ } -+ -+ plist_t err_node = plist_dict_get_item(dict, "Error"); -+ if (!err_node) { -+ return MOBILEACTIVATION_E_SUCCESS; -+ } else { -+ char *errmsg = NULL; -+ plist_get_string_val(err_node, &errmsg); -+ debug_info("ERROR: %s: %s", command, errmsg); -+ free(errmsg); -+ ret = MOBILEACTIVATION_E_REQUEST_FAILED; -+ } -+ return ret; -+} -+ -+static mobileactivation_error_t mobileactivation_send_command(mobileactivation_client_t client, const char* command, plist_t value, plist_t *result) -+{ -+ if (!client || !command || !result) -+ return MOBILEACTIVATION_E_INVALID_ARG; -+ -+ mobileactivation_error_t ret = MOBILEACTIVATION_E_UNKNOWN_ERROR; -+ *result = NULL; -+ -+ plist_t dict = plist_new_dict(); -+ plist_dict_set_item(dict, "Command", plist_new_string(command)); -+ if (value) { -+ plist_dict_set_item(dict, "Value", plist_copy(value)); -+ } -+ -+ ret = mobileactivation_error(property_list_service_send_binary_plist(client->parent, dict)); -+ plist_free(dict); -+ dict = NULL; -+ -+ ret = mobileactivation_error(property_list_service_receive_plist(client->parent, &dict)); -+ if (!dict) { -+ debug_info("ERROR: Did not get reply for %s command", command); -+ return MOBILEACTIVATION_E_PLIST_ERROR; -+ } -+ -+ *result = dict; -+ return mobileactivation_check_result(dict, command); -+} -+ -+LIBIMOBILEDEVICE_API mobileactivation_error_t mobileactivation_get_activation_state(mobileactivation_client_t client, plist_t *state) -+{ -+ if (!client || !state) -+ return MOBILEACTIVATION_E_INVALID_ARG; -+ -+ plist_t result = NULL; -+ mobileactivation_error_t ret = mobileactivation_send_command(client, "GetActivationStateRequest", NULL, &result); -+ if (ret == MOBILEACTIVATION_E_SUCCESS) { -+ plist_t node = plist_dict_get_item(result, "Value"); -+ if (!node) { -+ debug_info("ERROR: GetActivationStateRequest command returned success but has no value in reply"); -+ ret = MOBILEACTIVATION_E_UNKNOWN_ERROR; -+ } else { -+ *state = plist_copy(node); -+ } -+ } -+ plist_free(result); -+ result = NULL; -+ -+ return ret; -+} -+ -+LIBIMOBILEDEVICE_API mobileactivation_error_t mobileactivation_create_activation_info(mobileactivation_client_t client, plist_t *info) -+{ -+ if (!client || !info) -+ return MOBILEACTIVATION_E_INVALID_ARG; -+ -+ plist_t result = NULL; -+ mobileactivation_error_t ret = mobileactivation_send_command(client, "CreateActivationInfoRequest", NULL, &result); -+ if (ret == MOBILEACTIVATION_E_SUCCESS) { -+ plist_t node = plist_dict_get_item(result, "Value"); -+ if (!node) { -+ debug_info("ERROR: CreateActivationInfoRequest command returned success but has no value in reply"); -+ ret = MOBILEACTIVATION_E_UNKNOWN_ERROR; -+ } else { -+ *info = plist_copy(node); -+ } -+ } -+ plist_free(result); -+ result = NULL; -+ -+ return ret; -+} -+ -+LIBIMOBILEDEVICE_API mobileactivation_error_t mobileactivation_activate(mobileactivation_client_t client, plist_t activation_record) -+{ -+ if (!client || !activation_record) -+ return MOBILEACTIVATION_E_INVALID_ARG; -+ -+ plist_t result = NULL; -+ mobileactivation_error_t ret = mobileactivation_send_command(client, "HandleActivationInfoRequest", activation_record, &result); -+ plist_free(result); -+ result = NULL; -+ -+ return ret; -+} -+ -+LIBIMOBILEDEVICE_API mobileactivation_error_t mobileactivation_deactivate(mobileactivation_client_t client) -+{ -+ if (!client) -+ return MOBILEACTIVATION_E_INVALID_ARG; -+ -+ plist_t result = NULL; -+ mobileactivation_error_t ret = mobileactivation_send_command(client, "DeactivateRequest", NULL, &result); -+ plist_free(result); -+ result = NULL; -+ -+ return ret; -+} -diff --git a/src/mobileactivation.h b/src/mobileactivation.h -new file mode 100644 -index 0000000..49b9ebc ---- /dev/null -+++ b/src/mobileactivation.h -@@ -0,0 +1,32 @@ -+/* -+ * mobileactivation.h -+ * com.apple.mobileactivationd service header file. -+ * -+ * Copyright (c) 2016 Nikias Bassen, All Rights Reserved. -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -+ */ -+ -+#ifndef __MOBILEACTIVATION_H -+#define __MOBILEACTIVATION_H -+ -+#include "libimobiledevice/mobileactivation.h" -+#include "property_list_service.h" -+ -+struct mobileactivation_client_private { -+ property_list_service_client_t parent; -+}; -+ -+#endif --- -2.14.1 - - -From 0dbe76b4e75eef5d0e033aac99409fb6df36c512 Mon Sep 17 00:00:00 2001 -From: Nikias Bassen -Date: Mon, 3 Jul 2017 03:09:35 +0200 -Subject: [PATCH 64/65] mobileactivation: Add new functions required for - drmHandshake / session mode device activation - ---- - include/libimobiledevice/mobileactivation.h | 47 +++++++++++++++++- - src/mobileactivation.c | 75 ++++++++++++++++++++++++++++- - 2 files changed, 119 insertions(+), 3 deletions(-) - -diff --git a/include/libimobiledevice/mobileactivation.h b/include/libimobiledevice/mobileactivation.h -index bb977fe..bb1f3f4 100644 ---- a/include/libimobiledevice/mobileactivation.h -+++ b/include/libimobiledevice/mobileactivation.h -@@ -3,7 +3,7 @@ - * @brief Handle device activation and deactivation. - * \internal - * -- * Copyright (c) 2016 Nikias Bassen, All Rights Reserved. -+ * Copyright (c) 2016-2017 Nikias Bassen, All Rights Reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public -@@ -103,6 +103,20 @@ mobileactivation_error_t mobileactivation_client_free(mobileactivation_client_t - */ - mobileactivation_error_t mobileactivation_get_activation_state(mobileactivation_client_t client, plist_t *state); - -+/** -+ * Retrieves a session blob required for 'drmHandshake' via albert.apple.com. -+ * -+ * @param client The mobileactivation client -+ * @param blob Pointer to a plist_t variable that will be set to the -+ * session blob created by the mobielactivation service. The -+ * consumer is responsible for freeing the returned object using -+ * plist_free(). -+ * -+ * @return MOBILEACTIVATION_E_SUCCESS on success, or an MOBILEACTIVATION_E_* -+ * error code otherwise. -+ */ -+mobileactivation_error_t mobileactivation_create_activation_session_info(mobileactivation_client_t client, plist_t *blob); -+ - /** - * Retrieves the activation info required for device activation. - * -@@ -117,6 +131,24 @@ mobileactivation_error_t mobileactivation_get_activation_state(mobileactivation_ - */ - mobileactivation_error_t mobileactivation_create_activation_info(mobileactivation_client_t client, plist_t *info); - -+/** -+ * Retrieves the activation info required for device activation in 'session' -+ * mode. This function expects a handshake result retrieved from -+ * https://albert.apple.com/deviceservies/drmHandshake with a blob -+ * provided by mobileactivation_create_activation_session_info(). -+ * -+ * @param client The mobileactivation client -+ * @aram handshake_result The handshake result returned from drmHandshake -+ * @param info Pointer to a plist_t variable that will be set to the -+ * activation info created by the mobileactivation service. The -+ * consumer is responsible for freeing the returned object using -+ * plist_free(). -+ * -+ * @return MOBILEACTIVATION_E_SUCCESS on success, or an MOBILEACTIVATION_E_* -+ * error code otherwise. -+ */ -+mobileactivation_error_t mobileactivation_create_activation_info_with_session(mobileactivation_client_t client, plist_t handshake_result, plist_t *info); -+ - /** - * Activates the device with the given activation record. - * The activation record plist dictionary must be obtained using the -@@ -130,6 +162,19 @@ mobileactivation_error_t mobileactivation_create_activation_info(mobileactivatio - */ - mobileactivation_error_t mobileactivation_activate(mobileactivation_client_t client, plist_t activation_record); - -+/** -+ * Activates the device with the given activation record in 'session' mode. -+ * The activation record plist dictionary must be obtained using the -+ * activation protocol requesting from Apple's https webservice. -+ * -+ * @param client The mobileactivation client -+ * @param activation_record The activation record plist dictionary -+ * -+ * @return MOBILEACTIVATION_E_SUCCESS on success, or an MOBILEACTIVATION_E_* -+ * error code otherwise. -+ */ -+mobileactivation_error_t mobileactivation_activate_with_session(mobileactivation_client_t client, plist_t activation_record); -+ - /** - * Deactivates the device. - * -diff --git a/src/mobileactivation.c b/src/mobileactivation.c -index f14eb73..7ae35bb 100644 ---- a/src/mobileactivation.c -+++ b/src/mobileactivation.c -@@ -2,7 +2,7 @@ - * mobileactivation.c - * com.apple.mobileactivationd service implementation. - * -- * Copyright (c) 2016 Nikias Bassen, All Rights Reserved. -+ * Copyright (c) 2016-2017 Nikias Bassen, All Rights Reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public -@@ -89,6 +89,17 @@ LIBIMOBILEDEVICE_API mobileactivation_error_t mobileactivation_client_free(mobil - return MOBILEACTIVATION_E_SUCCESS; - } - -+static plist_t plist_data_from_plist(plist_t plist) -+{ -+ plist_t result = NULL; -+ char *xml = NULL; -+ uint32_t xml_len = 0; -+ plist_to_xml(plist, &xml, &xml_len); -+ result = plist_new_data(xml, xml_len); -+ free(xml); -+ return result; -+} -+ - static mobileactivation_error_t mobileactivation_check_result(plist_t dict, const char *command) - { - mobileactivation_error_t ret = MOBILEACTIVATION_E_UNKNOWN_ERROR; -@@ -104,8 +115,8 @@ static mobileactivation_error_t mobileactivation_check_result(plist_t dict, cons - char *errmsg = NULL; - plist_get_string_val(err_node, &errmsg); - debug_info("ERROR: %s: %s", command, errmsg); -- free(errmsg); - ret = MOBILEACTIVATION_E_REQUEST_FAILED; -+ free(errmsg); - } - return ret; - } -@@ -160,6 +171,26 @@ LIBIMOBILEDEVICE_API mobileactivation_error_t mobileactivation_get_activation_st - return ret; - } - -+LIBIMOBILEDEVICE_API mobileactivation_error_t mobileactivation_create_activation_session_info(mobileactivation_client_t client, plist_t *blob) -+{ -+ if (!client || !blob) -+ return MOBILEACTIVATION_E_INVALID_ARG; -+ -+ plist_t result = NULL; -+ mobileactivation_error_t ret = mobileactivation_send_command(client, "CreateTunnel1SessionInfoRequest", NULL, &result); -+ if (ret == MOBILEACTIVATION_E_SUCCESS) { -+ plist_t node = plist_dict_get_item(result, "Value"); -+ if (!node) { -+ debug_info("ERROR: CreateTunnel1SessionInfoRequest command returned success but has no value in reply"); -+ ret = MOBILEACTIVATION_E_UNKNOWN_ERROR; -+ } else { -+ *blob = plist_copy(node); -+ } -+ } -+ -+ return ret; -+} -+ - LIBIMOBILEDEVICE_API mobileactivation_error_t mobileactivation_create_activation_info(mobileactivation_client_t client, plist_t *info) - { - if (!client || !info) -@@ -179,6 +210,30 @@ LIBIMOBILEDEVICE_API mobileactivation_error_t mobileactivation_create_activation - plist_free(result); - result = NULL; - -+ return ret; -+} -+ -+LIBIMOBILEDEVICE_API mobileactivation_error_t mobileactivation_create_activation_info_with_session(mobileactivation_client_t client, plist_t handshake_response, plist_t *info) -+{ -+ if (!client || !info) -+ return MOBILEACTIVATION_E_INVALID_ARG; -+ -+ plist_t result = NULL; -+ plist_t data = plist_data_from_plist(handshake_response); -+ mobileactivation_error_t ret = mobileactivation_send_command(client, "CreateTunnel1ActivationInfoRequest", data, &result); -+ plist_free(data); -+ if (ret == MOBILEACTIVATION_E_SUCCESS) { -+ plist_t node = plist_dict_get_item(result, "Value"); -+ if (!node) { -+ debug_info("ERROR: CreateTunnel1ActivationInfoRequest command returned success but has no value in reply"); -+ ret = MOBILEACTIVATION_E_UNKNOWN_ERROR; -+ } else { -+ *info = plist_copy(node); -+ } -+ } -+ plist_free(result); -+ result = NULL; -+ - return ret; - } - -@@ -195,6 +250,22 @@ LIBIMOBILEDEVICE_API mobileactivation_error_t mobileactivation_activate(mobileac - return ret; - } - -+LIBIMOBILEDEVICE_API mobileactivation_error_t mobileactivation_activate_with_session(mobileactivation_client_t client, plist_t activation_record) -+{ -+ if (!client || !activation_record) -+ return MOBILEACTIVATION_E_INVALID_ARG; -+ -+ plist_t result = NULL; -+ plist_t data = plist_data_from_plist(activation_record); -+ mobileactivation_error_t ret = mobileactivation_send_command(client, "HandleActivationInfoWithSessionRequest", data, &result); -+ plist_free(data); -+ plist_free(result); -+ result = NULL; -+ -+ return ret; -+} -+ -+ - LIBIMOBILEDEVICE_API mobileactivation_error_t mobileactivation_deactivate(mobileactivation_client_t client) - { - if (!client) --- -2.14.1 - - -From 5a85432719fb3d18027d528f87d2a44b76fd3e12 Mon Sep 17 00:00:00 2001 -From: Nikias Bassen -Date: Sun, 13 Aug 2017 00:12:16 +0200 -Subject: [PATCH 65/65] lockdown: Don't explicitly validate pairing unless - we're dealing with an older device - -On newer iOS version, ValidatePair is not mandatory to gain trusted host -status. Starting with iOS 11, the ValidatePair request has been removed from -lockdownd and will throw an error. This commit adds a version check so that -ValidatePair is only called on devices prior iOS 7. ---- - src/idevice.c | 1 + - src/idevice.h | 1 + - src/lockdown.c | 37 +++++++++++++++++++++++++------------ - 3 files changed, 27 insertions(+), 12 deletions(-) - -diff --git a/src/idevice.c b/src/idevice.c -index 21b10ba..ead9b86 100644 ---- a/src/idevice.c -+++ b/src/idevice.c -@@ -256,6 +256,7 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_new(idevice_t * device, const char - dev->udid = strdup(muxdev.udid); - dev->conn_type = CONNECTION_USBMUXD; - dev->conn_data = (void*)(long)muxdev.handle; -+ dev->version = 0; - *device = dev; - return IDEVICE_E_SUCCESS; - } -diff --git a/src/idevice.h b/src/idevice.h -index 1354cc0..e46a7e5 100644 ---- a/src/idevice.h -+++ b/src/idevice.h -@@ -76,6 +76,7 @@ struct idevice_private { - char *udid; - enum connection_type conn_type; - void *conn_data; -+ int version; - }; - - #endif -diff --git a/src/lockdown.c b/src/lockdown.c -index 5251737..071697d 100644 ---- a/src/lockdown.c -+++ b/src/lockdown.c -@@ -707,6 +707,19 @@ LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_client_new_with_handshake(idevi - } - free(type); - -+ if (device->version == 0) { -+ plist_t p_version = NULL; -+ if (lockdownd_get_value(client_loc, NULL, "ProductVersion", &p_version) == LOCKDOWN_E_SUCCESS) { -+ int vers[3] = {0, 0, 0}; -+ char *s_version = NULL; -+ plist_get_string_val(p_version, &s_version); -+ if (s_version && sscanf(s_version, "%d.%d.%d", &vers[0], &vers[1], &vers[2]) >= 2) { -+ device->version = ((vers[0] & 0xFF) << 16) | ((vers[1] & 0xFF) << 8) | (vers[2] & 0xFF); -+ } -+ free(s_version); -+ } -+ } -+ - userpref_read_pair_record(client_loc->udid, &pair_record); - if (pair_record) { - pair_record_get_host_id(pair_record, &host_id); -@@ -723,18 +736,18 @@ LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_client_new_with_handshake(idevi - plist_free(pair_record); - pair_record = NULL; - -- /* in any case, we need to validate pairing to receive trusted host status */ -- ret = lockdownd_validate_pair(client_loc, NULL); -- -- /* if not paired yet, let's do it now */ -- if (LOCKDOWN_E_INVALID_HOST_ID == ret) { -- free(host_id); -- host_id = NULL; -- ret = lockdownd_pair(client_loc, NULL); -- if (LOCKDOWN_E_SUCCESS == ret) { -- ret = lockdownd_validate_pair(client_loc, NULL); -- } else if (LOCKDOWN_E_PAIRING_DIALOG_RESPONSE_PENDING == ret) { -- debug_info("Device shows the pairing dialog."); -+ if (device->version < 0x070000) { -+ /* for older devices, we need to validate pairing to receive trusted host status */ -+ ret = lockdownd_validate_pair(client_loc, NULL); -+ -+ /* if not paired yet, let's do it now */ -+ if (LOCKDOWN_E_INVALID_HOST_ID == ret) { -+ free(host_id); -+ host_id = NULL; -+ ret = lockdownd_pair(client_loc, NULL); -+ if (LOCKDOWN_E_SUCCESS == ret) { -+ ret = lockdownd_validate_pair(client_loc, NULL); -+ } - } - } - --- -2.14.1 - diff --git a/a7568f456d10f1aff61534e3216201a857865247...9b857fc42cdc4921e1e3f190c5ea907774e04758.patch b/a7568f456d10f1aff61534e3216201a857865247...9b857fc42cdc4921e1e3f190c5ea907774e04758.patch new file mode 100644 index 0000000..c58889f --- /dev/null +++ b/a7568f456d10f1aff61534e3216201a857865247...9b857fc42cdc4921e1e3f190c5ea907774e04758.patch @@ -0,0 +1,15694 @@ +From 344409e1d1ad917d377b256214c5411dda82e6b0 Mon Sep 17 00:00:00 2001 +From: Martin Szulecki +Date: Thu, 29 Jan 2015 00:12:56 +0100 +Subject: [PATCH 001/151] Post-release version bump to 1.2.1 + +--- + configure.ac | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/configure.ac b/configure.ac +index 44daa65..43da458 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -2,7 +2,7 @@ + # Process this file with autoconf to produce a configure script. + + AC_PREREQ(2.64) +-AC_INIT([libimobiledevice], [1.2.0], [https://github.com/libimobiledevice/libimobiledevice/issues],, [http://libimobiledevice.org]) ++AC_INIT([libimobiledevice], [1.2.1], [https://github.com/libimobiledevice/libimobiledevice/issues],, [http://libimobiledevice.org]) + AM_INIT_AUTOMAKE([dist-bzip2 no-dist-gzip check-news]) + m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES]) + AC_CONFIG_SRCDIR([src/]) +-- +2.23.0 + + +From 1ff3448d2e27f1bac8d2f0af8b8e952854860278 Mon Sep 17 00:00:00 2001 +From: Martin Szulecki +Date: Thu, 29 Jan 2015 22:21:27 +0100 +Subject: [PATCH 002/151] m4: Use python-config if available to fix Python 3 + support on newer distros + +--- + m4/ac_python_devel.m4 | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/m4/ac_python_devel.m4 b/m4/ac_python_devel.m4 +index 2e7406e..545c607 100644 +--- a/m4/ac_python_devel.m4 ++++ b/m4/ac_python_devel.m4 +@@ -151,6 +151,9 @@ $ac_distutils_result]) + # Check for Python include path + # + AC_MSG_CHECKING([for Python include path]) ++ if type $PYTHON-config; then ++ PYTHON_CPPFLAGS=`$PYTHON-config --includes` ++ fi + if test -z "$PYTHON_CPPFLAGS"; then + python_path=`$PYTHON -c "import distutils.sysconfig; \ + print(distutils.sysconfig.get_python_inc());"` +@@ -166,6 +169,9 @@ $ac_distutils_result]) + # Check for Python library path + # + AC_MSG_CHECKING([for Python library path]) ++ if type $PYTHON-config; then ++ PYTHON_LDFLAGS=`$PYTHON-config --ldflags` ++ fi + if test -z "$PYTHON_LDFLAGS"; then + # (makes two attempts to ensure we've got a version number + # from the interpreter) +-- +2.23.0 + + +From 65def891530879ffe9b45c1ccee64a6bed1ea93f Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Sun, 24 May 2015 00:12:48 +0200 +Subject: [PATCH 003/151] lockdown: Remove unneeded plist_free() calls since + entire dict is freed later + +--- + src/lockdown.c | 5 ----- + 1 file changed, 5 deletions(-) + +diff --git a/src/lockdown.c b/src/lockdown.c +index d1296c9..7cb3091 100644 +--- a/src/lockdown.c ++++ b/src/lockdown.c +@@ -960,8 +960,6 @@ static lockdownd_error_t lockdownd_do_pair(lockdownd_client_t client, lockdownd_ + if (extra_node && plist_get_node_type(extra_node) == PLIST_DATA) { + debug_info("Saving EscrowBag from response in pair record"); + plist_dict_set_item(pair_record_plist, USERPREF_ESCROW_BAG_KEY, plist_copy(extra_node)); +- plist_free(extra_node); +- extra_node = NULL; + } + + /* save previously retrieved wifi mac address in pair record */ +@@ -991,9 +989,6 @@ static lockdownd_error_t lockdownd_do_pair(lockdownd_client_t client, lockdownd_ + ret = lockdownd_strtoerr(value); + free(value); + } +- +- plist_free(error_node); +- error_node = NULL; + } + } + +-- +2.23.0 + + +From e1cac25e632955da0c3aeb2f16f49c5a1687f81c Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Fri, 10 Jul 2015 03:03:23 +0200 +Subject: [PATCH 004/151] lockdown: Add more error codes + +--- + cython/lockdown.pxi | 8 ++++++++ + include/libimobiledevice/lockdown.h | 4 ++++ + src/lockdown.c | 10 +++++++++- + 3 files changed, 21 insertions(+), 1 deletion(-) + +diff --git a/cython/lockdown.pxi b/cython/lockdown.pxi +index 7d903d6..c8d511e 100644 +--- a/cython/lockdown.pxi ++++ b/cython/lockdown.pxi +@@ -38,6 +38,10 @@ cdef extern from "libimobiledevice/lockdown.h": + LOCKDOWN_E_MISSING_ACTIVATION_RECORD + LOCKDOWN_E_SERVICE_PROHIBITED + LOCKDOWN_E_ESCROW_LOCKED ++ LOCKDOWN_E_PAIRING_PROHIBITED_OVER_THIS_CONNECTION ++ LOCKDOWN_E_FMIP_PROTECTED ++ LOCKDOWN_E_MC_PROTECTED ++ LOCKDOWN_E_MC_CHALLENGE_REQUIRED + LOCKDOWN_E_UNKNOWN_ERROR + + lockdownd_error_t lockdownd_client_new(idevice_t device, lockdownd_client_t *client, char *label) +@@ -103,6 +107,10 @@ cdef class LockdownError(BaseError): + LOCKDOWN_E_MISSING_ACTIVATION_RECORD: "Missing activation record", + LOCKDOWN_E_SERVICE_PROHIBITED: "Service prohibited", + LOCKDOWN_E_ESCROW_LOCKED: "Escrow locked", ++ LOCKDOWN_E_PAIRING_PROHIBITED_OVER_THIS_CONNECTION: "Pairing prohibited over this connection", ++ LOCKDOWN_E_FMIP_PROTECTED: "Find My iPhone/iPod/iPad protected", ++ LOCKDOWN_E_MC_PROTECTED: "MC protected", ++ LOCKDOWN_E_MC_CHALLENGE_REQUIRED: "MC challenge required", + LOCKDOWN_E_UNKNOWN_ERROR: "Unknown error" + } + BaseError.__init__(self, *args, **kwargs) +diff --git a/include/libimobiledevice/lockdown.h b/include/libimobiledevice/lockdown.h +index 076fa9d..46792a6 100644 +--- a/include/libimobiledevice/lockdown.h ++++ b/include/libimobiledevice/lockdown.h +@@ -73,6 +73,10 @@ typedef enum { + LOCKDOWN_E_MISSING_ACTIVATION_RECORD = -33, + LOCKDOWN_E_SERVICE_PROHIBITED = -34, + LOCKDOWN_E_ESCROW_LOCKED = -35, ++ LOCKDOWN_E_PAIRING_PROHIBITED_OVER_THIS_CONNECTION = -36, ++ LOCKDOWN_E_FMIP_PROTECTED = -37, ++ LOCKDOWN_E_MC_PROTECTED = -38, ++ LOCKDOWN_E_MC_CHALLENGE_REQUIRED = -39, + LOCKDOWN_E_UNKNOWN_ERROR = -256 + } lockdownd_error_t; + +diff --git a/src/lockdown.c b/src/lockdown.c +index 7cb3091..026d1d1 100644 +--- a/src/lockdown.c ++++ b/src/lockdown.c +@@ -3,7 +3,7 @@ + * com.apple.mobile.lockdownd service implementation. + * + * Copyright (c) 2009-2015 Martin Szulecki All Rights Reserved. +- * Copyright (c) 2014 Nikias Bassen. All Rights Reserved. ++ * Copyright (c) 2014-2015 Nikias Bassen All Rights Reserved. + * Copyright (c) 2010 Bryan Forbes All Rights Reserved. + * Copyright (c) 2008 Zach C. All Rights Reserved. + * +@@ -122,6 +122,14 @@ static lockdownd_error_t lockdownd_strtoerr(const char* name) + err = LOCKDOWN_E_SERVICE_PROHIBITED; + } else if (strcmp(name, "EscrowLocked") == 0) { + err = LOCKDOWN_E_ESCROW_LOCKED; ++ } else if (strcmp(name, "PairingProhibitedOverThisConnection") == 0) { ++ err = LOCKDOWN_E_PAIRING_PROHIBITED_OVER_THIS_CONNECTION; ++ } else if (strcmp(name, "FMiPProtected") == 0) { ++ err = LOCKDOWN_E_FMIP_PROTECTED; ++ } else if (strcmp(name, "MCProtected") == 0) { ++ err = LOCKDOWN_E_MC_PROTECTED; ++ } else if (strcmp(name, "MCChallengeRequired") == 0) { ++ err = LOCKDOWN_E_MC_CHALLENGE_REQUIRED; + } + + return err; +-- +2.23.0 + + +From f268393d4e447ac901879bee751d7350c495fed2 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Wed, 15 Jul 2015 07:22:37 +0200 +Subject: [PATCH 005/151] lockdown: Add new lockdownd_pair_with_options() + function + +--- + include/libimobiledevice/lockdown.h | 19 +++++++++++++++ + src/lockdown.c | 37 ++++++++++++++++++++++------- + 2 files changed, 47 insertions(+), 9 deletions(-) + +diff --git a/include/libimobiledevice/lockdown.h b/include/libimobiledevice/lockdown.h +index 46792a6..0e48eef 100644 +--- a/include/libimobiledevice/lockdown.h ++++ b/include/libimobiledevice/lockdown.h +@@ -295,6 +295,25 @@ lockdownd_error_t lockdownd_receive(lockdownd_client_t client, plist_t *plist); + */ + lockdownd_error_t lockdownd_pair(lockdownd_client_t client, lockdownd_pair_record_t pair_record); + ++ /** ++ * Pairs the device using the supplied pair record and passing the given options. ++ * ++ * @param client The lockdown client ++ * @param pair_record The pair record to use for pairing. If NULL is passed, then ++ * the pair records from the current machine are used. New records will be ++ * generated automatically when pairing is done for the first time. ++ * @param options The pairing options to pass. Can be NULL for no options. ++ * @param response If non-NULL a pointer to lockdownd's response dictionary is returned. ++ * The caller is responsible to free the response dictionary with plist_free(). ++ * ++ * @return LOCKDOWN_E_SUCCESS on success, LOCKDOWN_E_INVALID_ARG when client is NULL, ++ * LOCKDOWN_E_PLIST_ERROR if the pair_record certificates are wrong, ++ * LOCKDOWN_E_PAIRING_FAILED if the pairing failed, ++ * LOCKDOWN_E_PASSWORD_PROTECTED if the device is password protected, ++ * LOCKDOWN_E_INVALID_HOST_ID if the device does not know the caller's host id ++ */ ++lockdownd_error_t lockdownd_pair_with_options(lockdownd_client_t client, lockdownd_pair_record_t pair_record, plist_t options, plist_t *response); ++ + /** + * Validates if the device is paired with the given HostID. If successful the + * specified host will become trusted host of the device indicated by the +diff --git a/src/lockdown.c b/src/lockdown.c +index 026d1d1..85124bd 100644 +--- a/src/lockdown.c ++++ b/src/lockdown.c +@@ -848,6 +848,8 @@ leave: + * the pair records from the current machine are used. New records will be + * generated automatically when pairing is done for the first time. + * @param verb This is either "Pair", "ValidatePair" or "Unpair". ++ * @param options The pairing options to pass. ++ * @param response If non-NULL a pointer to lockdownd's response dictionary is returned. + * + * @return LOCKDOWN_E_SUCCESS on success, NP_E_INVALID_ARG when client is NULL, + * LOCKDOWN_E_PLIST_ERROR if the pair_record certificates are wrong, +@@ -855,7 +857,7 @@ leave: + * LOCKDOWN_E_PASSWORD_PROTECTED if the device is password protected, + * LOCKDOWN_E_INVALID_HOST_ID if the device does not know the caller's host id + */ +-static lockdownd_error_t lockdownd_do_pair(lockdownd_client_t client, lockdownd_pair_record_t pair_record, const char *verb) ++static lockdownd_error_t lockdownd_do_pair(lockdownd_client_t client, lockdownd_pair_record_t pair_record, const char *verb, plist_t options, plist_t *result) + { + if (!client) + return LOCKDOWN_E_INVALID_ARG; +@@ -915,9 +917,9 @@ static lockdownd_error_t lockdownd_do_pair(lockdownd_client_t client, lockdownd_ + plist_dict_set_item(dict, "Request", plist_new_string(verb)); + plist_dict_set_item(dict, "ProtocolVersion", plist_new_string(LOCKDOWN_PROTOCOL_VERSION)); + +- plist_t options = plist_new_dict(); +- plist_dict_set_item(options, "ExtendedPairingErrors", plist_new_bool(1)); +- plist_dict_set_item(dict, "PairingOptions", options); ++ if (options) { ++ plist_dict_set_item(dict, "PairingOptions", plist_copy(options)); ++ } + + /* send to device */ + ret = lockdownd_send(client, dict); +@@ -1010,25 +1012,42 @@ static lockdownd_error_t lockdownd_do_pair(lockdownd_client_t client, lockdownd_ + wifi_node = NULL; + } + +- plist_free(dict); +- dict = NULL; ++ if (result) { ++ *result = dict; ++ } else { ++ plist_free(dict); ++ dict = NULL; ++ } + + return ret; + } + + LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_pair(lockdownd_client_t client, lockdownd_pair_record_t pair_record) + { +- return lockdownd_do_pair(client, pair_record, "Pair"); ++ ++ plist_t options = plist_new_dict(); ++ plist_dict_set_item(options, "ExtendedPairingErrors", plist_new_bool(1)); ++ ++ lockdownd_error_t ret = lockdownd_do_pair(client, pair_record, "Pair", options, NULL); ++ ++ plist_free(options); ++ ++ return ret; ++} ++ ++LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_pair_with_options(lockdownd_client_t client, lockdownd_pair_record_t pair_record, plist_t options, plist_t *response) ++{ ++ return lockdownd_do_pair(client, pair_record, "Pair", options, response); + } + + LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_validate_pair(lockdownd_client_t client, lockdownd_pair_record_t pair_record) + { +- return lockdownd_do_pair(client, pair_record, "ValidatePair"); ++ return lockdownd_do_pair(client, pair_record, "ValidatePair", NULL, NULL); + } + + LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_unpair(lockdownd_client_t client, lockdownd_pair_record_t pair_record) + { +- return lockdownd_do_pair(client, pair_record, "Unpair"); ++ return lockdownd_do_pair(client, pair_record, "Unpair", NULL, NULL); + } + + LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_enter_recovery(lockdownd_client_t client) +-- +2.23.0 + + +From 2d5c2195bbdcc02774fa3f70a23759b3cb8b4aed Mon Sep 17 00:00:00 2001 +From: Martin Szulecki +Date: Tue, 6 Oct 2015 22:07:56 +0200 +Subject: [PATCH 006/151] Add missing "(void)" to functions to match public + headers + +--- + src/idevice.c | 2 +- + src/installation_proxy.c | 2 +- + src/mobilesync.c | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/idevice.c b/src/idevice.c +index ce27495..7c33cdd 100644 +--- a/src/idevice.c ++++ b/src/idevice.c +@@ -168,7 +168,7 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_event_subscribe(idevice_event_cb_t + return IDEVICE_E_SUCCESS; + } + +-LIBIMOBILEDEVICE_API idevice_error_t idevice_event_unsubscribe() ++LIBIMOBILEDEVICE_API idevice_error_t idevice_event_unsubscribe(void) + { + event_cb = NULL; + int res = usbmuxd_unsubscribe(); +diff --git a/src/installation_proxy.c b/src/installation_proxy.c +index e858e58..8bde154 100644 +--- a/src/installation_proxy.c ++++ b/src/installation_proxy.c +@@ -914,7 +914,7 @@ LIBIMOBILEDEVICE_API void instproxy_command_get_name(plist_t command, char** nam + } + } + +-LIBIMOBILEDEVICE_API plist_t instproxy_client_options_new() ++LIBIMOBILEDEVICE_API plist_t instproxy_client_options_new(void) + { + return plist_new_dict(); + } +diff --git a/src/mobilesync.c b/src/mobilesync.c +index 06fb1c1..d903cfe 100644 +--- a/src/mobilesync.c ++++ b/src/mobilesync.c +@@ -739,7 +739,7 @@ LIBIMOBILEDEVICE_API void mobilesync_anchors_free(mobilesync_anchors_t anchors) + anchors = NULL; + } + +-LIBIMOBILEDEVICE_API plist_t mobilesync_actions_new() ++LIBIMOBILEDEVICE_API plist_t mobilesync_actions_new(void) + { + return plist_new_dict(); + } +-- +2.23.0 + + +From d93043e6243e691a17135b221dd9275c10f8edbc Mon Sep 17 00:00:00 2001 +From: Martin Szulecki +Date: Tue, 6 Oct 2015 22:10:56 +0200 +Subject: [PATCH 007/151] tools: Use PACKAGE_URL define for homepage project + links in usage output + +--- + tools/idevice_id.c | 6 +++++- + tools/idevicebackup.c | 2 +- + tools/idevicebackup2.c | 6 +++++- + tools/idevicecrashreport.c | 6 +++++- + tools/idevicedate.c | 6 +++++- + tools/idevicedebug.c | 6 +++++- + tools/idevicedebugserverproxy.c | 6 +++++- + tools/idevicediagnostics.c | 6 +++++- + tools/ideviceenterrecovery.c | 6 +++++- + tools/ideviceimagemounter.c | 6 +++++- + tools/ideviceinfo.c | 6 +++++- + tools/idevicename.c | 6 +++++- + tools/idevicenotificationproxy.c | 6 +++++- + tools/idevicepair.c | 6 +++++- + tools/ideviceprovision.c | 7 ++++++- + tools/idevicescreenshot.c | 6 +++++- + tools/idevicesyslog.c | 6 +++++- + 17 files changed, 82 insertions(+), 17 deletions(-) + +diff --git a/tools/idevice_id.c b/tools/idevice_id.c +index 9629f8b..6f020ff 100644 +--- a/tools/idevice_id.c ++++ b/tools/idevice_id.c +@@ -19,6 +19,10 @@ + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + ++#ifdef HAVE_CONFIG_H ++#include ++#endif ++ + #include + #include + #include +@@ -42,7 +46,7 @@ static void print_usage(int argc, char **argv) + printf(" -d, --debug\t\tenable communication debugging\n"); + printf(" -h, --help\t\tprints usage information\n"); + printf("\n"); +- printf("Homepage: \n"); ++ printf("Homepage: <" PACKAGE_URL ">\n"); + } + + int main(int argc, char **argv) +diff --git a/tools/idevicebackup.c b/tools/idevicebackup.c +index eefaa6f..2619cc9 100644 +--- a/tools/idevicebackup.c ++++ b/tools/idevicebackup.c +@@ -674,7 +674,7 @@ static void print_usage(int argc, char **argv) + printf(" -u, --udid UDID\ttarget specific device by its 40-digit device UDID\n"); + printf(" -h, --help\t\tprints usage information\n"); + printf("\n"); +- printf("Homepage: \n"); ++ printf("Homepage: <" PACKAGE_URL ">\n"); + } + + int main(int argc, char *argv[]) +diff --git a/tools/idevicebackup2.c b/tools/idevicebackup2.c +index ead4dba..934cf39 100644 +--- a/tools/idevicebackup2.c ++++ b/tools/idevicebackup2.c +@@ -20,6 +20,10 @@ + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + ++#ifdef HAVE_CONFIG_H ++#include ++#endif ++ + #include + #include + #include +@@ -1139,7 +1143,7 @@ static void print_usage(int argc, char **argv) + printf(" -i, --interactive\trequest passwords interactively\n"); + printf(" -h, --help\t\tprints usage information\n"); + printf("\n"); +- printf("Homepage: \n"); ++ printf("Homepage: <" PACKAGE_URL ">\n"); + } + + int main(int argc, char *argv[]) +diff --git a/tools/idevicecrashreport.c b/tools/idevicecrashreport.c +index b74a660..7ac9baf 100644 +--- a/tools/idevicecrashreport.c ++++ b/tools/idevicecrashreport.c +@@ -20,6 +20,10 @@ + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + ++#ifdef HAVE_CONFIG_H ++#include ++#endif ++ + #include + #include + #include +@@ -298,7 +302,7 @@ static void print_usage(int argc, char **argv) + printf(" -u, --udid UDID\ttarget specific device by its 40-digit device UDID\n"); + printf(" -h, --help\t\tprints usage information\n"); + printf("\n"); +- printf("Homepage: \n"); ++ printf("Homepage: <" PACKAGE_URL ">\n"); + } + + int main(int argc, char* argv[]) { +diff --git a/tools/idevicedate.c b/tools/idevicedate.c +index f6bed7a..97243bb 100644 +--- a/tools/idevicedate.c ++++ b/tools/idevicedate.c +@@ -19,6 +19,10 @@ + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + ++#ifdef HAVE_CONFIG_H ++#include ++#endif ++ + #include + #include + #include +@@ -51,7 +55,7 @@ static void print_usage(int argc, char **argv) + printf(" -c, --sync\t\tset time of device to current system time\n"); + printf(" -h, --help\t\tprints usage information\n"); + printf("\n"); +- printf("Homepage: \n"); ++ printf("Homepage: <" PACKAGE_URL ">\n"); + } + + int main(int argc, char *argv[]) +diff --git a/tools/idevicedebug.c b/tools/idevicedebug.c +index 6a30ec4..b00893d 100644 +--- a/tools/idevicedebug.c ++++ b/tools/idevicedebug.c +@@ -19,6 +19,10 @@ + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + ++#ifdef HAVE_CONFIG_H ++#include ++#endif ++ + #include + #include + #include +@@ -188,7 +192,7 @@ static void print_usage(int argc, char **argv) + printf(" -d, --debug\t\tenable communication debugging\n"); + printf(" -h, --help\t\tprints usage information\n"); + printf("\n"); +- printf("Homepage: \n"); ++ printf("Homepage: <" PACKAGE_URL ">\n"); + } + + int main(int argc, char *argv[]) +diff --git a/tools/idevicedebugserverproxy.c b/tools/idevicedebugserverproxy.c +index 28bba5e..f270cdc 100644 +--- a/tools/idevicedebugserverproxy.c ++++ b/tools/idevicedebugserverproxy.c +@@ -19,6 +19,10 @@ + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + ++#ifdef HAVE_CONFIG_H ++#include ++#endif ++ + #include + #include + #include +@@ -70,7 +74,7 @@ static void print_usage(int argc, char **argv) + printf(" -u, --udid UDID\ttarget specific device by its 40-digit device UDID\n"); + printf(" -h, --help\t\tprints usage information\n"); + printf("\n"); +- printf("Homepage: \n"); ++ printf("Homepage: <" PACKAGE_URL ">\n"); + } + + static void *thread_device_to_client(void *data) +diff --git a/tools/idevicediagnostics.c b/tools/idevicediagnostics.c +index 992bc0a..8b6569d 100644 +--- a/tools/idevicediagnostics.c ++++ b/tools/idevicediagnostics.c +@@ -19,6 +19,10 @@ + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + ++#ifdef HAVE_CONFIG_H ++#include ++#endif ++ + #include + #include + #include +@@ -296,5 +300,5 @@ void print_usage(int argc, char **argv) + printf(" -u, --udid UDID\ttarget specific device by its 40-digit device UDID\n"); + printf(" -h, --help\t\tprints usage information\n"); + printf("\n"); +- printf("Homepage: \n"); ++ printf("Homepage: <" PACKAGE_URL ">\n"); + } +diff --git a/tools/ideviceenterrecovery.c b/tools/ideviceenterrecovery.c +index 3069be8..21c4ff6 100644 +--- a/tools/ideviceenterrecovery.c ++++ b/tools/ideviceenterrecovery.c +@@ -19,6 +19,10 @@ + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + ++#ifdef HAVE_CONFIG_H ++#include ++#endif ++ + #include + #include + #include +@@ -37,7 +41,7 @@ static void print_usage(int argc, char **argv) + printf(" -d, --debug\t\tenable communication debugging\n"); + printf(" -h, --help\t\tprints usage information\n"); + printf("\n"); +- printf("Homepage: \n"); ++ printf("Homepage: <" PACKAGE_URL ">\n"); + } + + int main(int argc, char *argv[]) +diff --git a/tools/ideviceimagemounter.c b/tools/ideviceimagemounter.c +index a0f4b83..ad3222a 100644 +--- a/tools/ideviceimagemounter.c ++++ b/tools/ideviceimagemounter.c +@@ -19,6 +19,10 @@ + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + ++#ifdef HAVE_CONFIG_H ++#include ++#endif ++ + #include + #define _GNU_SOURCE 1 + #define __USE_GNU 1 +@@ -66,7 +70,7 @@ static void print_usage(int argc, char **argv) + printf(" -d, --debug\t\tenable communication debugging\n"); + printf(" -h, --help\t\tprints usage information\n"); + printf("\n"); +- printf("Homepage: \n"); ++ printf("Homepage: <" PACKAGE_URL ">\n"); + } + + static void parse_opts(int argc, char **argv) +diff --git a/tools/ideviceinfo.c b/tools/ideviceinfo.c +index 641a036..40bcac6 100644 +--- a/tools/ideviceinfo.c ++++ b/tools/ideviceinfo.c +@@ -19,6 +19,10 @@ + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + ++#ifdef HAVE_CONFIG_H ++#include ++#endif ++ + #include + #include + #include +@@ -98,7 +102,7 @@ static void print_usage(int argc, char **argv) + printf(" %s\n", domains[i++]); + } + printf("\n"); +- printf("Homepage: \n"); ++ printf("Homepage: <" PACKAGE_URL ">\n"); + } + + int main(int argc, char *argv[]) +diff --git a/tools/idevicename.c b/tools/idevicename.c +index b5b9e62..013becc 100644 +--- a/tools/idevicename.c ++++ b/tools/idevicename.c +@@ -19,6 +19,10 @@ + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + ++#ifdef HAVE_CONFIG_H ++#include ++#endif ++ + #include + #include + #include +@@ -37,7 +41,7 @@ static void print_usage(void) + printf(" -u, --udid UDID\tuse UDID to target a specific device\n"); + printf(" -h, --help\t\tprint usage information\n"); + printf("\n"); +- printf("Homepage: \n"); ++ printf("Homepage: <" PACKAGE_URL ">\n"); + } + + int main(int argc, char** argv) +diff --git a/tools/idevicenotificationproxy.c b/tools/idevicenotificationproxy.c +index ff18eca..5e4ac9a 100644 +--- a/tools/idevicenotificationproxy.c ++++ b/tools/idevicenotificationproxy.c +@@ -19,6 +19,10 @@ + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + ++#ifdef HAVE_CONFIG_H ++#include ++#endif ++ + #include + #include + #include +@@ -69,7 +73,7 @@ static void print_usage(int argc, char **argv) + printf(" -u, --udid UDID\ttarget specific device by its 40-digit device UDID\n"); + printf(" -h, --help\t\tprints usage information\n"); + printf("\n"); +- printf("Homepage: \n"); ++ printf("Homepage: <" PACKAGE_URL ">\n"); + } + + static void notify_cb(const char *notification, void *user_data) +diff --git a/tools/idevicepair.c b/tools/idevicepair.c +index 237b168..f34369e 100644 +--- a/tools/idevicepair.c ++++ b/tools/idevicepair.c +@@ -20,6 +20,10 @@ + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + ++#ifdef HAVE_CONFIG_H ++#include ++#endif ++ + #include + #include + #include +@@ -71,7 +75,7 @@ static void print_usage(int argc, char **argv) + printf(" -u, --udid UDID target specific device by its 40-digit device UDID\n"); + printf(" -h, --help prints usage information\n"); + printf("\n"); +- printf("Homepage: \n"); ++ printf("Homepage: <" PACKAGE_URL ">\n"); + } + + static void parse_opts(int argc, char **argv) +diff --git a/tools/ideviceprovision.c b/tools/ideviceprovision.c +index 9517af8..4915c05 100644 +--- a/tools/ideviceprovision.c ++++ b/tools/ideviceprovision.c +@@ -19,6 +19,11 @@ + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ ++ ++#ifdef HAVE_CONFIG_H ++#include ++#endif ++ + #include + #include + #include +@@ -57,7 +62,7 @@ static void print_usage(int argc, char **argv) + printf(" -x, --xml print XML output when using the 'dump' command\n"); + printf(" -h, --help prints usage information\n"); + printf("\n"); +- printf("Homepage: \n"); ++ printf("Homepage: <" PACKAGE_URL ">\n"); + } + + enum { +diff --git a/tools/idevicescreenshot.c b/tools/idevicescreenshot.c +index bff502c..da229e2 100644 +--- a/tools/idevicescreenshot.c ++++ b/tools/idevicescreenshot.c +@@ -19,6 +19,10 @@ + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + ++#ifdef HAVE_CONFIG_H ++#include ++#endif ++ + #include + #include + #include +@@ -147,5 +151,5 @@ void print_usage(int argc, char **argv) + printf(" -u, --udid UDID\ttarget specific device by its 40-digit device UDID\n"); + printf(" -h, --help\t\tprints usage information\n"); + printf("\n"); +- printf("Homepage: \n"); ++ printf("Homepage: <" PACKAGE_URL ">\n"); + } +diff --git a/tools/idevicesyslog.c b/tools/idevicesyslog.c +index 4bc4b45..47d2f8c 100644 +--- a/tools/idevicesyslog.c ++++ b/tools/idevicesyslog.c +@@ -19,6 +19,10 @@ + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + ++#ifdef HAVE_CONFIG_H ++#include "config.h" ++#endif ++ + #include + #include + #include +@@ -206,6 +210,6 @@ void print_usage(int argc, char **argv) + printf(" -u, --udid UDID\ttarget specific device by its 40-digit device UDID\n"); + printf(" -h, --help\t\tprints usage information\n"); + printf("\n"); +- printf("Homepage: \n"); ++ printf("Homepage: <" PACKAGE_URL ">\n"); + } + +-- +2.23.0 + + +From 40f7dd06496d5b1c8963f760a10a217df926cd85 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Fri, 9 Oct 2015 15:43:22 +0200 +Subject: [PATCH 008/151] common: Add missing gnutls/openssl CFLAGS to + Makefile.am + +--- + common/Makefile.am | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/common/Makefile.am b/common/Makefile.am +index a79094b..054e2a1 100644 +--- a/common/Makefile.am ++++ b/common/Makefile.am +@@ -1,6 +1,6 @@ + AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir) + +-AM_CFLAGS = $(GLOBAL_CFLAGS) $(libusbmuxd_CFLAGS) $(libplist_CFLAGS) $(LFS_CFLAGS) ++AM_CFLAGS = $(GLOBAL_CFLAGS) $(libusbmuxd_CFLAGS) $(libplist_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(openssl_CFLAGS) $(LFS_CFLAGS) + AM_LDFLAGS = $(libusbmuxd_LIBS) $(libplist_LIBS) ${libpthread_LIBS} + + noinst_LTLIBRARIES = libinternalcommon.la +-- +2.23.0 + + +From 6070126868069f2ee01ea9414f4cfbe5de285267 Mon Sep 17 00:00:00 2001 +From: "Jay Freeman (saurik)" +Date: Wed, 21 Oct 2015 00:39:14 -0700 +Subject: [PATCH 009/151] Fix installation_proxy when using GnuTLS instead of + OpenSSL + +--- + src/idevice.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/src/idevice.c b/src/idevice.c +index 7c33cdd..b776e84 100644 +--- a/src/idevice.c ++++ b/src/idevice.c +@@ -393,10 +393,13 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_receive_timeout(idevice_ + } + + if (connection->ssl_data) { +-#ifdef HAVE_OPENSSL + uint32_t received = 0; + while (received < len) { ++#ifdef HAVE_OPENSSL + int r = SSL_read(connection->ssl_data->session, (void*)((char*)(data+received)), (int)len-received); ++#else ++ ssize_t r = gnutls_record_recv(connection->ssl_data->session, (void*)(data+received), (size_t)len-received); ++#endif + if (r > 0) { + received += r; + } else { +@@ -404,9 +407,6 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_receive_timeout(idevice_ + } + } + debug_info("SSL_read %d, received %d", len, received); +-#else +- ssize_t received = gnutls_record_recv(connection->ssl_data->session, (void*)data, (size_t)len); +-#endif + if (received > 0) { + *recv_bytes = received; + return IDEVICE_E_SUCCESS; +-- +2.23.0 + + +From 2203f4cba9ddaacee1ad702b7948da0e59d33497 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Fri, 18 Dec 2015 20:46:46 +0100 +Subject: [PATCH 010/151] tools: Fix inverted abort condition in + idevicecrashreport + +This bug caused it to never wait for the 'ping' message from +the crashreportmover service +--- + tools/idevicecrashreport.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/idevicecrashreport.c b/tools/idevicecrashreport.c +index 7ac9baf..8c04fd1 100644 +--- a/tools/idevicecrashreport.c ++++ b/tools/idevicecrashreport.c +@@ -405,7 +405,7 @@ int main(int argc, char* argv[]) { + /* read "ping" message which indicates the crash logs have been moved to a safe harbor */ + char *ping = malloc(4); + int attempts = 0; +- while ((strncmp(ping, "ping", 4) != 0) && (attempts > 10)) { ++ while ((strncmp(ping, "ping", 4) != 0) && (attempts < 10)) { + uint32_t bytes = 0; + device_error = idevice_connection_receive_timeout(connection, ping, 4, &bytes, 2000); + if ((bytes == 0) && (device_error == IDEVICE_E_SUCCESS)) { +-- +2.23.0 + + +From cae19fa6cf28074b51ce421d64142f7ec1e1dde2 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Fri, 18 Dec 2015 21:01:01 +0100 +Subject: [PATCH 011/151] tools: idevicecrashreport: Propertly initialize + buffer used to check for ping message + +--- + tools/idevicecrashreport.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/tools/idevicecrashreport.c b/tools/idevicecrashreport.c +index 8c04fd1..8502938 100644 +--- a/tools/idevicecrashreport.c ++++ b/tools/idevicecrashreport.c +@@ -404,6 +404,7 @@ int main(int argc, char* argv[]) { + + /* read "ping" message which indicates the crash logs have been moved to a safe harbor */ + char *ping = malloc(4); ++ memset(ping, '\0', 4); + int attempts = 0; + while ((strncmp(ping, "ping", 4) != 0) && (attempts < 10)) { + uint32_t bytes = 0; +-- +2.23.0 + + +From decffad5f5a0320b1b6e9e8cda821534ba2ed0ca Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Tue, 22 Dec 2015 18:10:35 +0100 +Subject: [PATCH 012/151] tools: idevicecrashreport: Fix missing 0-term when + creating local filename + +When a .synced file is encountered, the .synced should be stripped off the +local filename. However the strncpy doesn't 0-terminate the string by itself +so the output filename usually contains some garbage characters at the end. +This commit properly 0-terminates the local filename to avoid this. +--- + tools/idevicecrashreport.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/tools/idevicecrashreport.c b/tools/idevicecrashreport.c +index 8502938..4d7f41c 100644 +--- a/tools/idevicecrashreport.c ++++ b/tools/idevicecrashreport.c +@@ -144,7 +144,9 @@ static int afc_client_copy_and_remove_crash_reports(afc_client_t afc, const char + char* p = strrchr(list[k], '.'); + if (p != NULL && !strncmp(p, ".synced", 7)) { + /* make sure to strip ".synced" extension as seen on iOS 5 */ +- strncpy(((char*)target_filename) + host_directory_length, list[k], strlen(list[k]) - 7); ++ int newlen = strlen(list[k]) - 7; ++ strncpy(((char*)target_filename) + host_directory_length, list[k], newlen); ++ target_filename[host_directory_length + newlen] = '\0'; + } else { + strcpy(((char*)target_filename) + host_directory_length, list[k]); + } +-- +2.23.0 + + +From df1f5c4d70d0c19ad40072f5246ca457e7f9849e Mon Sep 17 00:00:00 2001 +From: Joshua Hill +Date: Tue, 29 Dec 2015 22:27:17 +0100 +Subject: [PATCH 013/151] common: [security fix] Make sure sockets only listen + locally + +--- + common/socket.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/common/socket.c b/common/socket.c +index b276864..e2968a6 100644 +--- a/common/socket.c ++++ b/common/socket.c +@@ -172,7 +172,7 @@ int socket_create(uint16_t port) + + memset((void *) &saddr, 0, sizeof(saddr)); + saddr.sin_family = AF_INET; +- saddr.sin_addr.s_addr = htonl(INADDR_ANY); ++ saddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + saddr.sin_port = htons(port); + + if (0 > bind(sfd, (struct sockaddr *) &saddr, sizeof(saddr))) { +@@ -329,7 +329,7 @@ int socket_accept(int fd, uint16_t port) + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; +- addr.sin_addr.s_addr = htonl(INADDR_ANY); ++ addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + addr.sin_port = htons(port); + + addr_len = sizeof(addr); +-- +2.23.0 + + +From 35b0543ec2a54250be011a9ffdd1d70f2c1ced5c Mon Sep 17 00:00:00 2001 +From: BALATON Zoltan +Date: Wed, 23 Sep 2015 02:11:54 +0200 +Subject: [PATCH 014/151] idevicebackup: fix some timestamps that are relative + to the Mac epoch instead of Unix one + +--- + common/utils.h | 2 ++ + tools/idevicebackup.c | 4 ++-- + tools/idevicebackup2.c | 7 ++++--- + 3 files changed, 8 insertions(+), 5 deletions(-) + +diff --git a/common/utils.h b/common/utils.h +index 90cfa4a..8426bc0 100644 +--- a/common/utils.h ++++ b/common/utils.h +@@ -33,6 +33,8 @@ + #include + #include + ++#define MAC_EPOCH 978307200 ++ + #ifndef HAVE_STPCPY + char *stpcpy(char *s1, const char *s2); + #endif +diff --git a/tools/idevicebackup.c b/tools/idevicebackup.c +index 2619cc9..7e825de 100644 +--- a/tools/idevicebackup.c ++++ b/tools/idevicebackup.c +@@ -251,7 +251,7 @@ static plist_t mobilebackup_factory_info_plist_new(const char* udid) + if (value_node) + plist_dict_set_item(ret, "IMEI", plist_copy(value_node)); + +- plist_dict_set_item(ret, "Last Backup Date", plist_new_date(time(NULL), 0)); ++ plist_dict_set_item(ret, "Last Backup Date", plist_new_date(time(NULL) - MAC_EPOCH, 0)); + + value_node = plist_dict_get_item(root_node, "ProductType"); + plist_dict_set_item(ret, "Product Type", plist_copy(value_node)); +@@ -288,7 +288,7 @@ static void mobilebackup_info_update_last_backup_date(plist_t info_plist) + return; + + node = plist_dict_get_item(info_plist, "Last Backup Date"); +- plist_set_date_val(node, time(NULL), 0); ++ plist_set_date_val(node, time(NULL) - MAC_EPOCH, 0); + + node = NULL; + } +diff --git a/tools/idevicebackup2.c b/tools/idevicebackup2.c +index 934cf39..be5a1a0 100644 +--- a/tools/idevicebackup2.c ++++ b/tools/idevicebackup2.c +@@ -146,10 +146,10 @@ static void mobilebackup_afc_get_file_contents(afc_client_t afc, const char *fil + uint32_t bread = 0; + afc_file_read(afc, f, buf+done, 65536, &bread); + if (bread > 0) { ++ done += bread; + } else { + break; + } +- done += bread; + } + if (done == fsize) { + *size = fsize; +@@ -223,7 +223,7 @@ static plist_t mobilebackup_factory_info_plist_new(const char* udid, lockdownd_c + if (value_node) + plist_dict_set_item(ret, "IMEI", plist_copy(value_node)); + +- plist_dict_set_item(ret, "Last Backup Date", plist_new_date(time(NULL), 0)); ++ plist_dict_set_item(ret, "Last Backup Date", plist_new_date(time(NULL) - MAC_EPOCH, 0)); + + value_node = plist_dict_get_item(root_node, "PhoneNumber"); + if (value_node && (plist_get_node_type(value_node) == PLIST_STRING)) { +@@ -914,7 +914,8 @@ static void mb2_handle_list_directory(mobilebackup2_client_t mobilebackup2, plis + } + plist_dict_set_item(fdict, "DLFileType", plist_new_string(ftype)); + plist_dict_set_item(fdict, "DLFileSize", plist_new_uint(st.st_size)); +- plist_dict_set_item(fdict, "DLFileModificationDate", plist_new_date(st.st_mtime, 0)); ++ plist_dict_set_item(fdict, "DLFileModificationDate", ++ plist_new_date(st.st_mtime - MAC_EPOCH, 0)); + + plist_dict_set_item(dirlist, ep->d_name, fdict); + free(fpath); +-- +2.23.0 + + +From 15173c59a00a8e9c154bd6787e35c243c383160e Mon Sep 17 00:00:00 2001 +From: BALATON Zoltan +Date: Wed, 23 Sep 2015 02:15:34 +0200 +Subject: [PATCH 015/151] Avoid potential NULL pointer dereference (leading to + segfault) if functions are called with NULL arguments + +--- + src/installation_proxy.c | 14 +++++++++----- + src/lockdown.c | 2 +- + 2 files changed, 10 insertions(+), 6 deletions(-) + +diff --git a/src/installation_proxy.c b/src/installation_proxy.c +index 8bde154..9f367aa 100644 +--- a/src/installation_proxy.c ++++ b/src/installation_proxy.c +@@ -847,11 +847,12 @@ LIBIMOBILEDEVICE_API instproxy_error_t instproxy_status_get_error(plist_t status + + LIBIMOBILEDEVICE_API void instproxy_status_get_name(plist_t status, char **name) + { +- *name = NULL; + if (name) { + plist_t node = plist_dict_get_item(status, "Status"); + if (node) { + plist_get_string_val(node, name); ++ } else { ++ *name = NULL; + } + } + } +@@ -907,10 +908,13 @@ LIBIMOBILEDEVICE_API void instproxy_status_get_current_list(plist_t status, uint + + LIBIMOBILEDEVICE_API void instproxy_command_get_name(plist_t command, char** name) + { +- *name = NULL; +- plist_t node = plist_dict_get_item(command, "Command"); +- if (node) { +- plist_get_string_val(node, name); ++ if (name) { ++ plist_t node = plist_dict_get_item(command, "Command"); ++ if (node) { ++ plist_get_string_val(node, name); ++ } else { ++ *name = NULL; ++ } + } + } + +diff --git a/src/lockdown.c b/src/lockdown.c +index 85124bd..d2e8c74 100644 +--- a/src/lockdown.c ++++ b/src/lockdown.c +@@ -637,7 +637,7 @@ LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_get_device_name(lockdownd_clien + + LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_client_new(idevice_t device, lockdownd_client_t *client, const char *label) + { +- if (!client) ++ if (!device || !client) + return LOCKDOWN_E_INVALID_ARG; + + static struct lockdownd_service_descriptor service = { +-- +2.23.0 + + +From 692f7c9de72ca7fcaba51659972270d445751438 Mon Sep 17 00:00:00 2001 +From: BALATON Zoltan +Date: Wed, 23 Sep 2015 02:19:27 +0200 +Subject: [PATCH 016/151] Add new function to get the underlying file + descriptor of an idevice connection + +--- + include/libimobiledevice/libimobiledevice.h | 10 ++++++++++ + src/idevice.c | 16 ++++++++++++++++ + 2 files changed, 26 insertions(+) + +diff --git a/include/libimobiledevice/libimobiledevice.h b/include/libimobiledevice/libimobiledevice.h +index 016cadb..b125adf 100644 +--- a/include/libimobiledevice/libimobiledevice.h ++++ b/include/libimobiledevice/libimobiledevice.h +@@ -239,6 +239,16 @@ idevice_error_t idevice_connection_enable_ssl(idevice_connection_t connection); + */ + idevice_error_t idevice_connection_disable_ssl(idevice_connection_t connection); + ++/** ++ * Get the underlying file descriptor for a connection ++ * ++ * @param connection The connection to get fd of ++ * @param fd Pointer to an int where the fd is stored ++ * ++ * @return IDEVICE_E_SUCCESS if ok, otherwise an error code. ++ */ ++idevice_error_t idevice_connection_get_fd(idevice_connection_t connection, int *fd); ++ + /* misc */ + + /** +diff --git a/src/idevice.c b/src/idevice.c +index b776e84..5912aeb 100644 +--- a/src/idevice.c ++++ b/src/idevice.c +@@ -463,6 +463,22 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_receive(idevice_connecti + return internal_connection_receive(connection, data, len, recv_bytes); + } + ++LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_get_fd(idevice_connection_t connection, int *fd) ++{ ++ if (!connection || !fd) { ++ return IDEVICE_E_INVALID_ARG; ++ } ++ ++ idevice_error_t result = IDEVICE_E_UNKNOWN_ERROR; ++ if (connection->type == CONNECTION_USBMUXD) { ++ *fd = (int)(long)connection->data; ++ result = IDEVICE_E_SUCCESS; ++ } else { ++ debug_info("Unknown connection type %d", connection->type); ++ } ++ return result; ++} ++ + LIBIMOBILEDEVICE_API idevice_error_t idevice_get_handle(idevice_t device, uint32_t *handle) + { + if (!device) +-- +2.23.0 + + +From cca7ce77d8bde998933ef8a753407b043806c1a6 Mon Sep 17 00:00:00 2001 +From: Matthias Ringwald +Date: Fri, 29 Apr 2016 20:27:32 +0200 +Subject: [PATCH 017/151] idevicedebug: Show error if container info not found + +--- + tools/idevicedebug.c | 18 ++++++++---------- + 1 file changed, 8 insertions(+), 10 deletions(-) + +diff --git a/tools/idevicedebug.c b/tools/idevicedebug.c +index b00893d..f18254a 100644 +--- a/tools/idevicedebug.c ++++ b/tools/idevicedebug.c +@@ -317,16 +317,14 @@ int main(int argc, char *argv[]) + instproxy_client_free(instproxy_client); + instproxy_client = NULL; + +- if (container) { +- if (plist_get_node_type(container) == PLIST_STRING) { +- plist_get_string_val(container, &working_directory); +- debug_info("working_directory: %s\n", working_directory); +- plist_free(container); +- } else { +- plist_free(container); +- fprintf(stderr, "Could not determine container path for bundle identifier %s.\n", bundle_identifier); +- goto cleanup; +- } ++ if (container && (plist_get_node_type(container) == PLIST_STRING)) { ++ plist_get_string_val(container, &working_directory); ++ debug_info("working_directory: %s\n", working_directory); ++ plist_free(container); ++ } else { ++ plist_free(container); ++ fprintf(stderr, "Could not determine container path for bundle identifier %s.\n", bundle_identifier); ++ goto cleanup; + } + + /* start and connect to debugserver */ +-- +2.23.0 + + +From d29709f86ef66239551493b4b4a4fc7eb62771ce Mon Sep 17 00:00:00 2001 +From: Xiao Deng +Date: Fri, 29 Apr 2016 20:34:13 +0200 +Subject: [PATCH 018/151] diagnostics_relay: Plug small memory leak + +--- + src/diagnostics_relay.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/diagnostics_relay.c b/src/diagnostics_relay.c +index f67c4df..79e041e 100644 +--- a/src/diagnostics_relay.c ++++ b/src/diagnostics_relay.c +@@ -104,6 +104,7 @@ LIBIMOBILEDEVICE_API diagnostics_relay_error_t diagnostics_relay_client_free(dia + if (property_list_service_client_free(client->parent) != PROPERTY_LIST_SERVICE_E_SUCCESS) { + return DIAGNOSTICS_RELAY_E_UNKNOWN_ERROR; + } ++ free(client); + return DIAGNOSTICS_RELAY_E_SUCCESS; + } + +-- +2.23.0 + + +From 11c1cd64edb750b3035c6b147e6b9712a6caefe2 Mon Sep 17 00:00:00 2001 +From: Xiao Deng +Date: Fri, 29 Apr 2016 20:34:52 +0200 +Subject: [PATCH 019/151] file_relay: Plug small memory leak + +--- + src/file_relay.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/file_relay.c b/src/file_relay.c +index 5055556..455855b 100644 +--- a/src/file_relay.c ++++ b/src/file_relay.c +@@ -59,6 +59,7 @@ LIBIMOBILEDEVICE_API file_relay_error_t file_relay_client_free(file_relay_client + if (property_list_service_client_free(client->parent) != PROPERTY_LIST_SERVICE_E_SUCCESS) { + return FILE_RELAY_E_UNKNOWN_ERROR; + } ++ free(client); + return FILE_RELAY_E_SUCCESS; + } + +-- +2.23.0 + + +From ed48703dd92a223ae4a59393aade75b70367d833 Mon Sep 17 00:00:00 2001 +From: Kylie McClain +Date: Tue, 23 Jun 2015 04:28:41 -0400 +Subject: [PATCH 020/151] configure.ac: Don't always explicitly disable openssl + +--- + configure.ac | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/configure.ac b/configure.ac +index 43da458..bade848 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -120,7 +120,7 @@ AC_SUBST([CYTHON_SUB]) + AC_ARG_ENABLE([openssl], + [AS_HELP_STRING([--disable-openssl], + [Do not look for OpenSSL])], +- [use_openssl=no], ++ [use_openssl=$enableval], + [use_openssl=yes]) + + pkg_req_openssl="openssl >= 0.9.8" +-- +2.23.0 + + +From e6486dbd29470939ed032972ca693888465e9ff4 Mon Sep 17 00:00:00 2001 +From: Arty Gus +Date: Fri, 29 Apr 2016 21:47:32 +0200 +Subject: [PATCH 022/151] configure.ac: Only check for pthread support on + non-win32 platforms + +--- + configure.ac | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/configure.ac b/configure.ac +index bade848..26fe819 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -37,7 +37,6 @@ AC_PROG_LIBTOOL + PKG_CHECK_MODULES(libusbmuxd, libusbmuxd >= $LIBUSBMUXD_VERSION) + PKG_CHECK_MODULES(libplist, libplist >= $LIBPLIST_VERSION) + PKG_CHECK_MODULES(libplistmm, libplist++ >= $LIBPLISTMM_VERSION) +-AC_CHECK_LIB(pthread, [pthread_create, pthread_mutex_lock], [AC_SUBST(libpthread_LIBS,[-lpthread])], [AC_MSG_ERROR([libpthread is required to build libimobiledevice])]) + + # Checks for header files. + AC_HEADER_STDC +@@ -82,6 +81,10 @@ case ${host_os} in + esac + AM_CONDITIONAL(WIN32, test x$win32 = xtrue) + ++if test "x$win32" != xtrue; then ++ AC_CHECK_LIB(pthread, [pthread_create, pthread_mutex_lock], [AC_SUBST(libpthread_LIBS,[-lpthread])], [AC_MSG_ERROR([libpthread is required to build libimobiledevice])]) ++fi ++ + # Cython Python Bindings + AC_ARG_WITH([cython], + [AS_HELP_STRING([--without-cython], +-- +2.23.0 + + +From 2a5868411c57e25802d2f16fd6b77601f10d0b72 Mon Sep 17 00:00:00 2001 +From: Nikos Mavrogiannopoulos +Date: Fri, 29 Apr 2016 22:58:34 +0200 +Subject: [PATCH 023/151] Updated gnutls certificate callback to new API + (backwards compatible) + +--- + src/idevice.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/src/idevice.c b/src/idevice.c +index 5912aeb..f2de6a3 100644 +--- a/src/idevice.c ++++ b/src/idevice.c +@@ -642,7 +642,11 @@ static const char *ssl_error_to_string(int e) + /** + * Internally used gnutls callback function that gets called during handshake. + */ ++#if GNUTLS_VERSION_NUMBER >= 0x020b07 ++static int internal_cert_callback(gnutls_session_t session, const gnutls_datum_t * req_ca_rdn, int nreqs, const gnutls_pk_algorithm_t * sign_algos, int sign_algos_length, gnutls_retr2_st * st) ++#else + static int internal_cert_callback(gnutls_session_t session, const gnutls_datum_t * req_ca_rdn, int nreqs, const gnutls_pk_algorithm_t * sign_algos, int sign_algos_length, gnutls_retr_st * st) ++#endif + { + int res = -1; + gnutls_certificate_type_t type = gnutls_certificate_type_get(session); +@@ -650,7 +654,12 @@ static int internal_cert_callback(gnutls_session_t session, const gnutls_datum_t + ssl_data_t ssl_data = (ssl_data_t)gnutls_session_get_ptr(session); + if (ssl_data && ssl_data->host_privkey && ssl_data->host_cert) { + debug_info("Passing certificate"); ++#if GNUTLS_VERSION_NUMBER >= 0x020b07 ++ st->cert_type = type; ++ st->key_type = GNUTLS_PRIVKEY_X509; ++#else + st->type = type; ++#endif + st->ncerts = 1; + st->cert.x509 = &ssl_data->host_cert; + st->key.x509 = ssl_data->host_privkey; +@@ -759,7 +768,11 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_enable_ssl(idevice_conne + debug_info("enabling SSL mode"); + errno = 0; + gnutls_certificate_allocate_credentials(&ssl_data_loc->certificate); ++#if GNUTLS_VERSION_NUMBER >= 0x020b07 ++ gnutls_certificate_set_retrieve_function(ssl_data_loc->certificate, internal_cert_callback); ++#else + gnutls_certificate_client_set_retrieve_function(ssl_data_loc->certificate, internal_cert_callback); ++#endif + gnutls_init(&ssl_data_loc->session, GNUTLS_CLIENT); + gnutls_priority_set_direct(ssl_data_loc->session, "NONE:+VERS-SSL3.0:+ANON-DH:+RSA:+AES-128-CBC:+AES-256-CBC:+SHA1:+MD5:+COMP-NULL", NULL); + gnutls_credentials_set(ssl_data_loc->session, GNUTLS_CRD_CERTIFICATE, ssl_data_loc->certificate); +-- +2.23.0 + + +From 6ce120c168b0f0a0146e505649864b5b07dc5093 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Wed, 15 Jun 2016 02:01:36 +0200 +Subject: [PATCH 024/151] Fix SSL version negotiation with newer versions of + OpenSSL + +--- + src/idevice.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/idevice.c b/src/idevice.c +index f2de6a3..4e8c56e 100644 +--- a/src/idevice.c ++++ b/src/idevice.c +@@ -703,7 +703,7 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_enable_ssl(idevice_conne + } + BIO_set_fd(ssl_bio, (int)(long)connection->data, BIO_NOCLOSE); + +- SSL_CTX *ssl_ctx = SSL_CTX_new(SSLv3_method()); ++ SSL_CTX *ssl_ctx = SSL_CTX_new(SSLv23_method()); + if (ssl_ctx == NULL) { + debug_info("ERROR: Could not create SSL context."); + BIO_free(ssl_bio); +-- +2.23.0 + + +From dc4c75d8a0a2ef557ac9ba0d2e080805621a3d98 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Thu, 16 Jun 2016 19:24:48 +0200 +Subject: [PATCH 025/151] Revert "Fix SSL version negotiation with newer + versions of OpenSSL" + +This reverts commit 6ce120c168b0f0a0146e505649864b5b07dc5093. +The change had the negative effect that connecting to older iOS devices wouldn't work anymore. +--- + src/idevice.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/idevice.c b/src/idevice.c +index 4e8c56e..f2de6a3 100644 +--- a/src/idevice.c ++++ b/src/idevice.c +@@ -703,7 +703,7 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_enable_ssl(idevice_conne + } + BIO_set_fd(ssl_bio, (int)(long)connection->data, BIO_NOCLOSE); + +- SSL_CTX *ssl_ctx = SSL_CTX_new(SSLv23_method()); ++ SSL_CTX *ssl_ctx = SSL_CTX_new(SSLv3_method()); + if (ssl_ctx == NULL) { + debug_info("ERROR: Could not create SSL context."); + BIO_free(ssl_bio); +-- +2.23.0 + + +From 13bf235cac2201747de11652cf14fe2714ca0718 Mon Sep 17 00:00:00 2001 +From: David Weinstein +Date: Mon, 21 Mar 2016 17:45:59 -0400 +Subject: [PATCH 026/151] Fix SSL version negotiation for newer versions of + OpenSSL + +Depending on the OpenSSL version (and custom distribution patches), `SSLv3_method()` +would return NULL on some systems and also `SSLv23_method()` fails with some older +iOS versions... +--- + src/idevice.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/idevice.c b/src/idevice.c +index f2de6a3..1dcdae2 100644 +--- a/src/idevice.c ++++ b/src/idevice.c +@@ -703,7 +703,7 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_enable_ssl(idevice_conne + } + BIO_set_fd(ssl_bio, (int)(long)connection->data, BIO_NOCLOSE); + +- SSL_CTX *ssl_ctx = SSL_CTX_new(SSLv3_method()); ++ SSL_CTX *ssl_ctx = SSL_CTX_new(TLSv1_method()); + if (ssl_ctx == NULL) { + debug_info("ERROR: Could not create SSL context."); + BIO_free(ssl_bio); +-- +2.23.0 + + +From a94c5c827a786844b56e8e36ddaed6239f32d86c Mon Sep 17 00:00:00 2001 +From: "Jay Freeman (saurik)" +Date: Wed, 27 Jul 2016 02:46:27 -0700 +Subject: [PATCH 027/151] lockdown: remove unnecessary check for pair record + file during pairing + +During device pairing the code in lockdownd_do_pair() is checking if there +is a pair record on disk for the current device, and then requests it from +usbmuxd. This additional check is not only unnecessary since usbmuxd can +obviously only return a pair record if it exists, but is also causing issues +on newer versions of macOS where /var/db/lockdown is mode 700. +--- + src/lockdown.c | 10 +++------- + 1 file changed, 3 insertions(+), 7 deletions(-) + +diff --git a/src/lockdown.c b/src/lockdown.c +index d2e8c74..904267e 100644 +--- a/src/lockdown.c ++++ b/src/lockdown.c +@@ -893,13 +893,9 @@ static lockdownd_error_t lockdownd_do_pair(lockdownd_client_t client, lockdownd_ + lockdownd_get_value(client, NULL, "WiFiAddress", &wifi_node); + } else { + /* use existing pair record */ +- if (userpref_has_pair_record(client->udid)) { +- userpref_read_pair_record(client->udid, &pair_record_plist); +- if (!pair_record_plist) { +- return LOCKDOWN_E_INVALID_CONF; +- } +- } else { +- return LOCKDOWN_E_INVALID_HOST_ID; ++ userpref_read_pair_record(client->udid, &pair_record_plist); ++ if (!pair_record_plist) { ++ return LOCKDOWN_E_INVALID_CONF; + } + } + } +-- +2.23.0 + + +From 18811d92c940018aeb3916780960d8f085eb9f32 Mon Sep 17 00:00:00 2001 +From: "Jay Freeman (saurik)" +Date: Wed, 27 Jul 2016 02:46:47 -0700 +Subject: [PATCH 028/151] userpref: Remove obsoleted function + userpref_has_pair_record() + +Since pair records are meanwhile handled by usbmuxd there is no need to check +for the existence of a pair record on disk. Asking usbmuxd for a pair record of +a given UDID is sufficient to know if it exists or not. +--- + common/userpref.c | 29 ----------------------------- + 1 file changed, 29 deletions(-) + +diff --git a/common/userpref.c b/common/userpref.c +index f88a123..d22c7f5 100644 +--- a/common/userpref.c ++++ b/common/userpref.c +@@ -191,35 +191,6 @@ int userpref_read_system_buid(char **system_buid) + return res; + } + +-/** +- * Determines whether this device has been connected to this system before. +- * +- * @param udid The device UDID as given by the device. +- * +- * @return 1 if the device has been connected previously to this configuration +- * or 0 otherwise. +- */ +-int userpref_has_pair_record(const char *udid) +-{ +- int ret = 0; +- const char *config_path = NULL; +- char *config_file = NULL; +- struct stat st; +- +- if (!udid) return 0; +- +- /* first get config file */ +- config_path = userpref_get_config_dir(); +- config_file = string_concat(config_path, DIR_SEP_S, udid, USERPREF_CONFIG_EXTENSION, NULL); +- +- if ((stat(config_file, &st) == 0) && S_ISREG(st.st_mode)) +- ret = 1; +- +- free(config_file); +- +- return ret; +-} +- + /** + * Fills a list with UDIDs of devices that have been connected to this + * system before, i.e. for which a public key file exists. +-- +2.23.0 + + +From 72643b2b83990b9cf97cc84b285b30763d44a72d Mon Sep 17 00:00:00 2001 +From: "Jay Freeman (saurik)" +Date: Tue, 2 Aug 2016 03:08:04 -0700 +Subject: [PATCH 029/151] idevice: Update GnuTLS code to support iOS 10 + +As of iOS 10 beta 4, the GnuTLS implementation idevice_connection_enable_ssl +needs to be updated to support TLS. Using +VERS-TLS-ALL did not work on some +of the devices I tested and I wasn't sure how to fix it, but +VERS-TLS1.0 is +working on every device I've tested: iOS 9.0.2, 10.0b4, 8.1.1, 6.0, and 3.0. +--- + src/idevice.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/idevice.c b/src/idevice.c +index 1dcdae2..b6dfe4e 100644 +--- a/src/idevice.c ++++ b/src/idevice.c +@@ -774,7 +774,7 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_enable_ssl(idevice_conne + gnutls_certificate_client_set_retrieve_function(ssl_data_loc->certificate, internal_cert_callback); + #endif + gnutls_init(&ssl_data_loc->session, GNUTLS_CLIENT); +- gnutls_priority_set_direct(ssl_data_loc->session, "NONE:+VERS-SSL3.0:+ANON-DH:+RSA:+AES-128-CBC:+AES-256-CBC:+SHA1:+MD5:+COMP-NULL", NULL); ++ 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); + gnutls_credentials_set(ssl_data_loc->session, GNUTLS_CRD_CERTIFICATE, ssl_data_loc->certificate); + gnutls_session_set_ptr(ssl_data_loc->session, ssl_data_loc); + +-- +2.23.0 + + +From 00f8e5733f716da8032606566eac7a9e2e49514d Mon Sep 17 00:00:00 2001 +From: "Jay Freeman (saurik)" +Date: Tue, 9 Aug 2016 17:18:14 -0700 +Subject: [PATCH 030/151] lockdown: return LOCKDOWN_E_INVALID_HOST_ID when + missing pair record + +When the check of /var/db/lockdown was removed, lockdownd_do_pair started to +always return LOCKDOWN_E_INVALID_CONF instead of usually (but not always...) +returning LOCKDOWN_E_INVALID_HOST_ID for devices not currently paired. This +change not only breaks some third-party code, but also breaks the other code +in this library calling this function (lockdownd_client_new_with_handshake). +--- + src/lockdown.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/lockdown.c b/src/lockdown.c +index 904267e..cae950b 100644 +--- a/src/lockdown.c ++++ b/src/lockdown.c +@@ -895,7 +895,7 @@ static lockdownd_error_t lockdownd_do_pair(lockdownd_client_t client, lockdownd_ + /* use existing pair record */ + userpref_read_pair_record(client->udid, &pair_record_plist); + if (!pair_record_plist) { +- return LOCKDOWN_E_INVALID_CONF; ++ return LOCKDOWN_E_INVALID_HOST_ID; + } + } + } +-- +2.23.0 + + +From 6aecc7228dbb30b4db48374ffb4ae4a1616bdd95 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Sun, 18 Sep 2016 16:18:20 +0200 +Subject: [PATCH 031/151] idevicebackup2: Fix removal of Snapshot dir during + backup with iOS 10+ + +DLMessageRemoveItems needs to recursively remove directories and this +commit implements that. +--- + tools/idevicebackup2.c | 101 +++++++++++++++++++++++++++++++---------- + 1 file changed, 78 insertions(+), 23 deletions(-) + +diff --git a/tools/idevicebackup2.c b/tools/idevicebackup2.c +index be5a1a0..c822d7f 100644 +--- a/tools/idevicebackup2.c ++++ b/tools/idevicebackup2.c +@@ -192,6 +192,74 @@ static int mkdir_with_parents(const char *dir, int mode) + return res; + } + ++static int remove_file(const char* path) ++{ ++ int e = 0; ++#ifdef WIN32 ++ if (!DeleteFile(path)) { ++ e = win32err_to_errno(GetLastError()); ++ } ++#else ++ if (remove(path) < 0) { ++ e = errno; ++ } ++#endif ++ return e; ++} ++ ++static int remove_directory(const char* path) ++{ ++ int e = 0; ++#ifdef WIN32 ++ if (!RemoveDirectory(path)) { ++ e = win32err_to_errno(GetLastError()); ++ } ++#else ++ if (remove(path) < 0) { ++ e = errno; ++ } ++#endif ++ return e; ++} ++ ++static int rmdir_recursive(const char* path) ++{ ++ DIR* cur_dir = opendir(path); ++ if (cur_dir) { ++ struct dirent* ep; ++ while ((ep = readdir(cur_dir))) { ++ if ((strcmp(ep->d_name, ".") == 0) || (strcmp(ep->d_name, "..") == 0)) { ++ continue; ++ } ++ char *fpath = string_build_path(path, ep->d_name, NULL); ++ if (fpath) { ++ struct stat st; ++ if (stat(fpath, &st) == 0) { ++ int res = 0; ++ if (S_ISDIR(st.st_mode)) { ++ res = rmdir_recursive(fpath); ++ } else { ++ res = remove_file(fpath); ++ } ++ if (res != 0) { ++ free(fpath); ++ closedir(cur_dir); ++ return res; ++ } ++ } else { ++ free(fpath); ++ closedir(cur_dir); ++ return errno; ++ } ++ } ++ free(fpath); ++ } ++ closedir(cur_dir); ++ } ++ ++ return remove_directory(path); ++} ++ + static plist_t mobilebackup_factory_info_plist_new(const char* udid, lockdownd_client_t lockdown, afc_client_t afc) + { + /* gather data from lockdown */ +@@ -1895,14 +1963,10 @@ checkpoint: + free(str); + char *oldpath = string_build_path(backup_directory, key, NULL); + +-#ifdef WIN32 + if ((stat(newpath, &st) == 0) && S_ISDIR(st.st_mode)) +- RemoveDirectory(newpath); ++ rmdir_recursive(newpath); + else +- DeleteFile(newpath); +-#else +- remove(newpath); +-#endif ++ remove_file(newpath); + if (rename(oldpath, newpath) < 0) { + printf("Renameing '%s' to '%s' failed: %s (%d)\n", oldpath, newpath, strerror(errno), errno); + errcode = errno_to_device_error(errno); +@@ -1951,27 +2015,18 @@ checkpoint: + } + char *newpath = string_build_path(backup_directory, str, NULL); + free(str); +-#ifdef WIN32 + int res = 0; +- if ((stat(newpath, &st) == 0) && S_ISDIR(st.st_mode)) +- res = RemoveDirectory(newpath); +- else +- res = DeleteFile(newpath); +- if (!res) { +- int e = win32err_to_errno(GetLastError()); +- if (!suppress_warning) +- printf("Could not remove '%s': %s (%d)\n", newpath, strerror(e), e); +- errcode = errno_to_device_error(e); +- errdesc = strerror(e); ++ if ((stat(newpath, &st) == 0) && S_ISDIR(st.st_mode)) { ++ res = rmdir_recursive(newpath); ++ } else { ++ res = remove_file(newpath); + } +-#else +- if (remove(newpath) < 0) { ++ if (res != 0) { + if (!suppress_warning) +- printf("Could not remove '%s': %s (%d)\n", newpath, strerror(errno), errno); +- errcode = errno_to_device_error(errno); +- errdesc = strerror(errno); ++ printf("Could not remove '%s': %s (%d)\n", newpath, strerror(res), res); ++ errcode = errno_to_device_error(res); ++ errdesc = strerror(res); + } +-#endif + free(newpath); + } + } +-- +2.23.0 + + +From 98a096134b23be980a0aa56e775c5510f0e93595 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Sun, 18 Sep 2016 16:24:14 +0200 +Subject: [PATCH 032/151] idevicebackup2: Fix build on win32 after last commit + +--- + tools/idevicebackup2.c | 28 ++++++++++++++-------------- + 1 file changed, 14 insertions(+), 14 deletions(-) + +diff --git a/tools/idevicebackup2.c b/tools/idevicebackup2.c +index c822d7f..3b2c0af 100644 +--- a/tools/idevicebackup2.c ++++ b/tools/idevicebackup2.c +@@ -192,6 +192,20 @@ static int mkdir_with_parents(const char *dir, int mode) + return res; + } + ++#ifdef WIN32 ++static int win32err_to_errno(int err_value) ++{ ++ switch (err_value) { ++ case ERROR_FILE_NOT_FOUND: ++ return ENOENT; ++ case ERROR_ALREADY_EXISTS: ++ return EEXIST; ++ default: ++ return EFAULT; ++ } ++} ++#endif ++ + static int remove_file(const char* path) + { + int e = 0; +@@ -518,20 +532,6 @@ static int errno_to_device_error(int errno_value) + } + } + +-#ifdef WIN32 +-static int win32err_to_errno(int err_value) +-{ +- switch (err_value) { +- case ERROR_FILE_NOT_FOUND: +- return ENOENT; +- case ERROR_ALREADY_EXISTS: +- return EEXIST; +- default: +- return EFAULT; +- } +-} +-#endif +- + static int mb2_handle_send_file(mobilebackup2_client_t mobilebackup2, const char *backup_dir, const char *path, plist_t *errplist) + { + uint32_t nlen = 0; +-- +2.23.0 + + +From 3fc7a85778d85a1dda1c0c4bedc8467470468476 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Sun, 18 Sep 2016 16:42:26 +0200 +Subject: [PATCH 033/151] win32: Fix MinGW build by adding -lgdi32 to properly + link against OpenSSL + +--- + src/Makefile.am | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/Makefile.am b/src/Makefile.am +index da60386..5ced544 100644 +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -32,7 +32,7 @@ libimobiledevice_la_SOURCES = idevice.c idevice.h \ + + if WIN32 + libimobiledevice_la_LDFLAGS += -avoid-version +-libimobiledevice_la_LIBADD += -lole32 -lws2_32 ++libimobiledevice_la_LIBADD += -lole32 -lws2_32 -lgdi32 + endif + + pkgconfigdir = $(libdir)/pkgconfig +-- +2.23.0 + + +From 00424f40574641d1360c9b1115770f5cc5d19a72 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Fri, 23 Sep 2016 20:07:48 +0200 +Subject: [PATCH 034/151] idevicebackup2: Add installed application info to + Info.plist during backup + +For newer iOS versions, apparently >= iOS 8, iTunes stores information +about installed applications inside of the Info.plist file. This +commit mimics that behavior. +--- + tools/idevicebackup2.c | 115 +++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 110 insertions(+), 5 deletions(-) + +diff --git a/tools/idevicebackup2.c b/tools/idevicebackup2.c +index 3b2c0af..2c868d7 100644 +--- a/tools/idevicebackup2.c ++++ b/tools/idevicebackup2.c +@@ -40,6 +40,8 @@ + #include + #include + #include ++#include ++#include + #include "common/utils.h" + + #include +@@ -274,7 +276,24 @@ static int rmdir_recursive(const char* path) + return remove_directory(path); + } + +-static plist_t mobilebackup_factory_info_plist_new(const char* udid, lockdownd_client_t lockdown, afc_client_t afc) ++static char* get_uuid() ++{ ++ const char *chars = "ABCDEF0123456789"; ++ int i = 0; ++ char *uuid = (char*)malloc(sizeof(char) * 32); ++ ++ srand(time(NULL)); ++ ++ for (i = 0; i < 32; i++) { ++ uuid[i] = chars[rand() % 16]; ++ } ++ ++ uuid[32] = '\0'; ++ ++ return uuid; ++} ++ ++static plist_t mobilebackup_factory_info_plist_new(const char* udid, idevice_t device, lockdownd_client_t lockdown, afc_client_t afc) + { + /* gather data from lockdown */ + plist_t value_node = NULL; +@@ -286,6 +305,74 @@ static plist_t mobilebackup_factory_info_plist_new(const char* udid, lockdownd_c + /* get basic device information in one go */ + lockdownd_get_value(lockdown, NULL, NULL, &root_node); + ++ /* get a list of installed user applications */ ++ plist_t app_dict = plist_new_dict(); ++ plist_t installed_apps = plist_new_array(); ++ instproxy_client_t ip = NULL; ++ if (instproxy_client_start_service(device, &ip, "idevicebackup2") == INSTPROXY_E_SUCCESS) { ++ plist_t client_opts = instproxy_client_options_new(); ++ instproxy_client_options_add(client_opts, "ApplicationType", "User", NULL); ++ instproxy_client_options_set_return_attributes(client_opts, "CFBundleIdentifier", "ApplicationSINF", "iTunesMetadata", NULL); ++ ++ plist_t apps = NULL; ++ instproxy_browse(ip, client_opts, &apps); ++ ++ sbservices_client_t sbs = NULL; ++ if (sbservices_client_start_service(device, &sbs, "idevicebackup2") != SBSERVICES_E_SUCCESS) { ++ printf("Couldn't establish sbservices connection. Continuing anyway.\n"); ++ } ++ ++ if (apps && (plist_get_node_type(apps) == PLIST_ARRAY)) { ++ uint32_t app_count = plist_array_get_size(apps); ++ uint32_t i; ++ time_t starttime = time(NULL); ++ for (i = 0; i < app_count; i++) { ++ plist_t app_entry = plist_array_get_item(apps, i); ++ plist_t bundle_id = plist_dict_get_item(app_entry, "CFBundleIdentifier"); ++ if (bundle_id) { ++ char *bundle_id_str = NULL; ++ plist_array_append_item(installed_apps, plist_copy(bundle_id)); ++ ++ plist_get_string_val(bundle_id, &bundle_id_str); ++ plist_t sinf = plist_dict_get_item(app_entry, "ApplicationSINF"); ++ plist_t meta = plist_dict_get_item(app_entry, "iTunesMetadata"); ++ if (sinf && meta) { ++ plist_t adict = plist_new_dict(); ++ plist_dict_set_item(adict, "ApplicationSINF", plist_copy(sinf)); ++ if (sbs) { ++ char *pngdata = NULL; ++ uint64_t pngsize = 0; ++ sbservices_get_icon_pngdata(sbs, bundle_id_str, &pngdata, &pngsize); ++ if (pngdata) { ++ plist_dict_set_item(adict, "PlaceholderIcon", plist_new_data(pngdata, pngsize)); ++ free(pngdata); ++ } ++ } ++ plist_dict_set_item(adict, "iTunesMetadata", plist_copy(meta)); ++ plist_dict_set_item(app_dict, bundle_id_str, adict); ++ } ++ } ++ if ((time(NULL) - starttime) > 5) { ++ // make sure our lockdown connection doesn't time out in case this takes longer ++ lockdownd_query_type(lockdown, NULL); ++ starttime = time(NULL); ++ } ++ } ++ } ++ plist_free(apps); ++ ++ if (sbs) { ++ sbservices_client_free(sbs); ++ } ++ ++ instproxy_client_options_free(client_opts); ++ ++ instproxy_client_free(ip); ++ } ++ ++ /* Applications */ ++ plist_dict_set_item(ret, "Applications", app_dict); ++ + /* set fields we understand */ + value_node = plist_dict_get_item(root_node, "BuildVersion"); + plist_dict_set_item(ret, "Build Version", plist_copy(value_node)); +@@ -294,8 +381,9 @@ static plist_t mobilebackup_factory_info_plist_new(const char* udid, lockdownd_c + plist_dict_set_item(ret, "Device Name", plist_copy(value_node)); + plist_dict_set_item(ret, "Display Name", plist_copy(value_node)); + +- /* FIXME: How is the GUID generated? */ +- plist_dict_set_item(ret, "GUID", plist_new_string("---")); ++ char *uuid = get_uuid(); ++ plist_dict_set_item(ret, "GUID", plist_new_string(uuid)); ++ free(uuid); + + value_node = plist_dict_get_item(root_node, "IntegratedCircuitCardIdentity"); + if (value_node) +@@ -305,13 +393,21 @@ static plist_t mobilebackup_factory_info_plist_new(const char* udid, lockdownd_c + if (value_node) + plist_dict_set_item(ret, "IMEI", plist_copy(value_node)); + ++ /* Installed Applications */ ++ plist_dict_set_item(ret, "Installed Applications", installed_apps); ++ + plist_dict_set_item(ret, "Last Backup Date", plist_new_date(time(NULL) - MAC_EPOCH, 0)); + ++ value_node = plist_dict_get_item(root_node, "MobileEquipmentIdentifier"); ++ plist_dict_set_item(ret, "MEID", plist_copy(value_node)); ++ + value_node = plist_dict_get_item(root_node, "PhoneNumber"); + if (value_node && (plist_get_node_type(value_node) == PLIST_STRING)) { + plist_dict_set_item(ret, "Phone Number", plist_copy(value_node)); + } + ++ /* FIXME Product Name */ ++ + value_node = plist_dict_get_item(root_node, "ProductType"); + plist_dict_set_item(ret, "Product Type", plist_copy(value_node)); + +@@ -349,6 +445,7 @@ static plist_t mobilebackup_factory_info_plist_new(const char* udid, lockdownd_c + "PhotosFolderAlbums", + "PhotosFolderName", + "PhotosFolderPrefs", ++ "VoiceMemos.plist", + "iPhotoAlbumPrefs", + "iTunesApplicationIDs", + "iTunesPrefs", +@@ -375,7 +472,15 @@ static plist_t mobilebackup_factory_info_plist_new(const char* udid, lockdownd_c + lockdownd_get_value(lockdown, "com.apple.iTunes", NULL, &itunes_settings); + plist_dict_set_item(ret, "iTunes Settings", itunes_settings ? itunes_settings : plist_new_dict()); + +- plist_dict_set_item(ret, "iTunes Version", plist_new_string("10.0.1")); ++ /* since we usually don't have iTunes, let's get the minimum required iTunes version from the device */ ++ value_node = NULL; ++ lockdownd_get_value(lockdown, "com.apple.mobile.iTunes", "MinITunesVersion", &value_node); ++ if (value_node) { ++ plist_dict_set_item(ret, "iTunes Version", plist_copy(value_node)); ++ plist_free(value_node); ++ } else { ++ plist_dict_set_item(ret, "iTunes Version", plist_new_string("10.0.1")); ++ } + + plist_free(root_node); + +@@ -1688,7 +1793,7 @@ checkpoint: + plist_free(info_plist); + info_plist = NULL; + } +- info_plist = mobilebackup_factory_info_plist_new(udid, lockdown, afc); ++ info_plist = mobilebackup_factory_info_plist_new(udid, device, lockdown, afc); + remove(info_path); + plist_write_to_filename(info_plist, info_path, PLIST_FORMAT_XML); + free(info_path); +-- +2.23.0 + + +From 1fa41702b6c7b8b169a33b79125d3b24f23c2da8 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Tue, 4 Oct 2016 14:37:57 +0200 +Subject: [PATCH 035/151] idevicebackup2: Fix assertion occuring when copying + non-present MEID + +--- + tools/idevicebackup2.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/tools/idevicebackup2.c b/tools/idevicebackup2.c +index 2c868d7..eb78b06 100644 +--- a/tools/idevicebackup2.c ++++ b/tools/idevicebackup2.c +@@ -399,7 +399,8 @@ static plist_t mobilebackup_factory_info_plist_new(const char* udid, idevice_t d + plist_dict_set_item(ret, "Last Backup Date", plist_new_date(time(NULL) - MAC_EPOCH, 0)); + + value_node = plist_dict_get_item(root_node, "MobileEquipmentIdentifier"); +- plist_dict_set_item(ret, "MEID", plist_copy(value_node)); ++ if (value_node) ++ plist_dict_set_item(ret, "MEID", plist_copy(value_node)); + + value_node = plist_dict_get_item(root_node, "PhoneNumber"); + if (value_node && (plist_get_node_type(value_node) == PLIST_STRING)) { +-- +2.23.0 + + +From c8c7adfd0e910ba5763777a25ce99f4f9143073f Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Wed, 5 Oct 2016 17:07:09 +0200 +Subject: [PATCH 036/151] idevicebackup2: Suppress repeated printing of global + status when 100% is reached + +--- + tools/idevicebackup2.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/tools/idevicebackup2.c b/tools/idevicebackup2.c +index eb78b06..7b15897 100644 +--- a/tools/idevicebackup2.c ++++ b/tools/idevicebackup2.c +@@ -1999,6 +1999,7 @@ checkpoint: + int file_count = 0; + int errcode = 0; + const char *errdesc = NULL; ++ int progress_finished = 0; + + /* process series of DLMessage* operations */ + do { +@@ -2226,7 +2227,10 @@ checkpoint: + } + + /* print status */ +- if (overall_progress > 0) { ++ if ((overall_progress > 0) && !progress_finished) { ++ if (overall_progress >= 100.0f) { ++ progress_finished = 1; ++ } + print_progress_real(overall_progress, 0); + PRINT_VERBOSE(1, " Finished\n"); + } +-- +2.23.0 + + +From 5dd8b52915cb5d9be91549366e989b28f3e29890 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Fri, 21 Oct 2016 14:29:56 +0200 +Subject: [PATCH 037/151] idevicebackup2: Use remove_file() wrapper instead of + remove() + +--- + tools/idevicebackup2.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/tools/idevicebackup2.c b/tools/idevicebackup2.c +index 7b15897..f47ff33 100644 +--- a/tools/idevicebackup2.c ++++ b/tools/idevicebackup2.c +@@ -960,7 +960,7 @@ static int mb2_handle_receive_files(mobilebackup2_client_t mobilebackup2, plist_ + PRINT_VERBOSE(1, "Found new flag %02x\n", code); + } + +- remove(bname); ++ remove_file(bname); + f = fopen(bname, "wb"); + while (f && (code == CODE_FILE_DATA)) { + blocksize = nlen-1; +@@ -1030,7 +1030,7 @@ static int mb2_handle_receive_files(mobilebackup2_client_t mobilebackup2, plist_ + fname = (char*)malloc(nlen-1); + mobilebackup2_receive_raw(mobilebackup2, fname, nlen-1, &r); + free(fname); +- remove(bname); ++ remove_file(bname); + } + + /* clean up */ +@@ -1795,7 +1795,7 @@ checkpoint: + info_plist = NULL; + } + info_plist = mobilebackup_factory_info_plist_new(udid, device, lockdown, afc); +- remove(info_path); ++ remove_file(info_path); + plist_write_to_filename(info_plist, info_path, PLIST_FORMAT_XML); + free(info_path); + +-- +2.23.0 + + +From 2c16751bafb41a049e30f211c2a21c3b8c68259e Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Fri, 21 Oct 2016 14:51:02 +0200 +Subject: [PATCH 038/151] idevicebackup2: Don't report an error when file to + remove doesn't exist + +--- + tools/idevicebackup2.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/idevicebackup2.c b/tools/idevicebackup2.c +index f47ff33..d355200 100644 +--- a/tools/idevicebackup2.c ++++ b/tools/idevicebackup2.c +@@ -2128,7 +2128,7 @@ checkpoint: + } else { + res = remove_file(newpath); + } +- if (res != 0) { ++ if (res != 0 && res != ENOENT) { + if (!suppress_warning) + printf("Could not remove '%s': %s (%d)\n", newpath, strerror(res), res); + errcode = errno_to_device_error(res); +-- +2.23.0 + + +From 8c37b9ca13211c197f3452356b73114c39f549fd Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Wed, 2 Nov 2016 16:31:04 +0100 +Subject: [PATCH 039/151] idevicebackup2: Fix heap buffer out-of-bounds write + caused by wrong buffer size + +--- + tools/idevicebackup2.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/idevicebackup2.c b/tools/idevicebackup2.c +index d355200..bb7f5c3 100644 +--- a/tools/idevicebackup2.c ++++ b/tools/idevicebackup2.c +@@ -280,7 +280,7 @@ static char* get_uuid() + { + const char *chars = "ABCDEF0123456789"; + int i = 0; +- char *uuid = (char*)malloc(sizeof(char) * 32); ++ char *uuid = (char*)malloc(sizeof(char) * 33); + + srand(time(NULL)); + +-- +2.23.0 + + +From 23069d10341ce637fdad7321d447c53752dba48c Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Fri, 4 Nov 2016 02:11:39 +0100 +Subject: [PATCH 040/151] userpref: [GnuTLS] Fix pairing record generation and + improve error handling + +In newer GnuTLS versions the parameters supplied to +gnutls_x509_privkey_import_rsa_raw() are actually checked for somewhat +sane values. Since we were passing the same values for all parameters, +this check fails and the device certificate is never generated. +However due to missing checks the pairing record was saved anyway, with +an empty device certificate. This led to TLS errors during communication, +leading to the "GnuTLS: Error in pull function" error message appearing +and the communication to fail. +This commit fixes the issue by passing some sane values, and also improves +the overall error handling during generation of the paring record. +--- + common/userpref.c | 85 +++++++++++++++++++++++++---------------------- + 1 file changed, 45 insertions(+), 40 deletions(-) + +diff --git a/common/userpref.c b/common/userpref.c +index d22c7f5..3ae503a 100644 +--- a/common/userpref.c ++++ b/common/userpref.c +@@ -643,15 +643,13 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da + gnutls_x509_crt_export(host_cert, GNUTLS_X509_FMT_PEM, host_cert_pem.data, &host_cert_export_size); + host_cert_pem.size = host_cert_export_size; + +- ret = USERPREF_E_UNKNOWN_ERROR; +- + gnutls_datum_t modulus = { NULL, 0 }; + gnutls_datum_t exponent = { NULL, 0 }; + + /* now decode the PEM encoded key */ +- gnutls_datum_t der_pub_key; +- if (GNUTLS_E_SUCCESS == gnutls_pem_base64_decode_alloc("RSA PUBLIC KEY", &public_key, &der_pub_key)) { +- ++ gnutls_datum_t der_pub_key = { NULL, 0 }; ++ int gnutls_error = gnutls_pem_base64_decode_alloc("RSA PUBLIC KEY", &public_key, &der_pub_key); ++ if (GNUTLS_E_SUCCESS == gnutls_error) { + /* initalize asn.1 parser */ + ASN1_TYPE pkcs1 = ASN1_TYPE_EMPTY; + if (ASN1_SUCCESS == asn1_array2tree(pkcs1_asn1_tab, &pkcs1, NULL)) { +@@ -670,8 +668,14 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da + + ret1 = asn1_read_value(asn1_pub_key, "modulus", modulus.data, (int*)&modulus.size); + ret2 = asn1_read_value(asn1_pub_key, "publicExponent", exponent.data, (int*)&exponent.size); +- if (ASN1_SUCCESS == ret1 && ASN1_SUCCESS == ret2) +- ret = USERPREF_E_SUCCESS; ++ if (ret1 != ASN1_SUCCESS || ret2 != ASN1_SUCCESS) { ++ gnutls_free(modulus.data); ++ modulus.data = NULL; ++ modulus.size = 0; ++ gnutls_free(exponent.data); ++ exponent.data = NULL; ++ exponent.size = 0; ++ } + } + if (asn1_pub_key) + asn1_delete_structure(&asn1_pub_key); +@@ -679,12 +683,15 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da + if (pkcs1) + asn1_delete_structure(&pkcs1); + } else { +- debug_info("WARNING: Could not read public key"); ++ debug_info("ERROR: Could not parse public key: %s", gnutls_strerror(gnutls_error)); + } + +- /* now generate certificates */ +- if (USERPREF_E_SUCCESS == ret && 0 != modulus.size && 0 != exponent.size) { +- gnutls_datum_t essentially_null = { (unsigned char*)strdup("abababababababab"), strlen("abababababababab") }; ++ /* generate device certificate */ ++ if (modulus.data && 0 != modulus.size && exponent.data && 0 != exponent.size) { ++ ++ gnutls_datum_t prime_p = { (unsigned char*)"\x00\xca\x4a\x03\x13\xdf\x9d\x7a\xfd", 9 }; ++ gnutls_datum_t prime_q = { (unsigned char*)"\x00\xf2\xff\xe0\x15\xd1\x60\x37\x63", 9 }; ++ gnutls_datum_t coeff = { (unsigned char*)"\x32\x07\xf1\x68\x57\xdf\x9a\xf4", 8 }; + + gnutls_x509_privkey_t fake_privkey; + gnutls_x509_crt_t dev_cert; +@@ -692,8 +699,9 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da + gnutls_x509_privkey_init(&fake_privkey); + gnutls_x509_crt_init(&dev_cert); + +- if (GNUTLS_E_SUCCESS == gnutls_x509_privkey_import_rsa_raw(fake_privkey, &modulus, &exponent, &essentially_null, &essentially_null, &essentially_null, &essentially_null)) { +- /* generate device certificate */ ++ gnutls_error = gnutls_x509_privkey_import_rsa_raw(fake_privkey, &modulus, &exponent, &exponent, &prime_p, &prime_q, &coeff); ++ if (GNUTLS_E_SUCCESS == gnutls_error) { ++ /* now generate device certificate */ + gnutls_x509_crt_set_key(dev_cert, fake_privkey); + gnutls_x509_crt_set_serial(dev_cert, "\x00", 1); + gnutls_x509_crt_set_version(dev_cert, 3); +@@ -712,9 +720,8 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da + } + + gnutls_x509_crt_set_key_usage(dev_cert, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT); +- gnutls_x509_crt_sign(dev_cert, root_cert, root_privkey); +- +- if (USERPREF_E_SUCCESS == ret) { ++ gnutls_error = gnutls_x509_crt_sign(dev_cert, root_cert, root_privkey); ++ if (GNUTLS_E_SUCCESS == gnutls_error) { + /* if everything went well, export in PEM format */ + size_t export_size = 0; + gnutls_x509_crt_export(dev_cert, GNUTLS_X509_FMT_PEM, NULL, &export_size); +@@ -722,13 +729,11 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da + gnutls_x509_crt_export(dev_cert, GNUTLS_X509_FMT_PEM, dev_cert_pem.data, &export_size); + dev_cert_pem.size = export_size; + } else { +- debug_info("ERROR: Signing device certificate with root private key failed!"); ++ debug_info("ERROR: Signing device certificate with root private key failed: %s", gnutls_strerror(gnutls_error)); + } ++ } else { ++ debug_info("ERROR: Failed to import RSA key data: %s", gnutls_strerror(gnutls_error)); + } +- +- if (essentially_null.data) +- free(essentially_null.data); +- + gnutls_x509_crt_deinit(dev_cert); + gnutls_x509_privkey_deinit(fake_privkey); + } +@@ -743,27 +748,27 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da + + gnutls_free(der_pub_key.data); + #endif +- if (NULL != root_cert_pem.data && 0 != root_cert_pem.size && +- NULL != host_cert_pem.data && 0 != host_cert_pem.size) ++ ++ /* make sure that we have all we need */ ++ if (root_cert_pem.data && 0 != root_cert_pem.size ++ && root_key_pem.data && 0 != root_key_pem.size ++ && host_cert_pem.data && 0 != host_cert_pem.size ++ && host_key_pem.data && 0 != host_key_pem.size ++ && dev_cert_pem.data && 0 != dev_cert_pem.size) { ++ /* now set keys and certificates */ ++ pair_record_set_item_from_key_data(pair_record, USERPREF_DEVICE_CERTIFICATE_KEY, &dev_cert_pem); ++ pair_record_set_item_from_key_data(pair_record, USERPREF_HOST_PRIVATE_KEY_KEY, &host_key_pem); ++ pair_record_set_item_from_key_data(pair_record, USERPREF_HOST_CERTIFICATE_KEY, &host_cert_pem); ++ pair_record_set_item_from_key_data(pair_record, USERPREF_ROOT_PRIVATE_KEY_KEY, &root_key_pem); ++ pair_record_set_item_from_key_data(pair_record, USERPREF_ROOT_CERTIFICATE_KEY, &root_cert_pem); + ret = USERPREF_E_SUCCESS; ++ } + +- /* now set keys and certificates */ +- pair_record_set_item_from_key_data(pair_record, USERPREF_DEVICE_CERTIFICATE_KEY, &dev_cert_pem); +- pair_record_set_item_from_key_data(pair_record, USERPREF_HOST_PRIVATE_KEY_KEY, &host_key_pem); +- pair_record_set_item_from_key_data(pair_record, USERPREF_HOST_CERTIFICATE_KEY, &host_cert_pem); +- pair_record_set_item_from_key_data(pair_record, USERPREF_ROOT_PRIVATE_KEY_KEY, &root_key_pem); +- pair_record_set_item_from_key_data(pair_record, USERPREF_ROOT_CERTIFICATE_KEY, &root_cert_pem); +- +- if (dev_cert_pem.data) +- free(dev_cert_pem.data); +- if (root_key_pem.data) +- free(root_key_pem.data); +- if (root_cert_pem.data) +- free(root_cert_pem.data); +- if (host_key_pem.data) +- free(host_key_pem.data); +- if (host_cert_pem.data) +- free(host_cert_pem.data); ++ free(dev_cert_pem.data); ++ free(root_key_pem.data); ++ free(root_cert_pem.data); ++ free(host_key_pem.data); ++ free(host_cert_pem.data); + + return ret; + } +-- +2.23.0 + + +From a1c728578930fb49e45497d1be7c9bc0c83607f1 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Sun, 27 Nov 2016 14:27:33 +0100 +Subject: [PATCH 041/151] idevicebackup2: Plug some small memory leaks + +--- + tools/idevicebackup2.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +diff --git a/tools/idevicebackup2.c b/tools/idevicebackup2.c +index bb7f5c3..8dc32c5 100644 +--- a/tools/idevicebackup2.c ++++ b/tools/idevicebackup2.c +@@ -351,6 +351,7 @@ static plist_t mobilebackup_factory_info_plist_new(const char* udid, idevice_t d + plist_dict_set_item(adict, "iTunesMetadata", plist_copy(meta)); + plist_dict_set_item(app_dict, bundle_id_str, adict); + } ++ free(bundle_id_str); + } + if ((time(NULL) - starttime) > 5) { + // make sure our lockdown connection doesn't time out in case this takes longer +@@ -2003,10 +2004,8 @@ checkpoint: + + /* process series of DLMessage* operations */ + do { +- if (dlmsg) { +- free(dlmsg); +- dlmsg = NULL; +- } ++ free(dlmsg); ++ dlmsg = NULL; + mobilebackup2_receive_message(mobilebackup2, &message, &dlmsg); + if (!message || !dlmsg) { + PRINT_VERBOSE(1, "Device is not ready yet. Going to try again in 2 seconds...\n"); +@@ -2236,11 +2235,9 @@ checkpoint: + } + + files_out: +- if (message) +- plist_free(message); ++ plist_free(message); + message = NULL; +- if (dlmsg) +- free(dlmsg); ++ free(dlmsg); + dlmsg = NULL; + + if (quit_flag > 0) { +@@ -2256,6 +2253,9 @@ files_out: + } + } while (1); + ++ plist_free(message); ++ free(dlmsg); ++ + /* report operation status to user */ + switch (cmd) { + case CMD_CLOUD: +-- +2.23.0 + + +From 2a9e6fe37467bfb13b415d7654f825269e08603f Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Thu, 1 Dec 2016 03:43:05 +0100 +Subject: [PATCH 042/151] misagent: Add new misagent_copy_all() function + (introduced in iOS 9.3) + +--- + include/libimobiledevice/misagent.h | 24 ++++++++++++++++- + src/misagent.c | 40 +++++++++++++++++++++++++++++ + 2 files changed, 63 insertions(+), 1 deletion(-) + +diff --git a/include/libimobiledevice/misagent.h b/include/libimobiledevice/misagent.h +index 92165f2..09af57a 100644 +--- a/include/libimobiledevice/misagent.h ++++ b/include/libimobiledevice/misagent.h +@@ -101,7 +101,7 @@ misagent_error_t misagent_client_free(misagent_client_t client); + misagent_error_t misagent_install(misagent_client_t client, plist_t profile); + + /** +- * Retrieves an array of all installed provisioning profiles. ++ * Retrieves all installed provisioning profiles (iOS 9.2.1 or below). + * + * @param client The connected misagent to use. + * @param profiles Pointer to a plist_t that will be set to a PLIST_ARRAY +@@ -110,12 +110,34 @@ misagent_error_t misagent_install(misagent_client_t client, plist_t profile); + * @return MISAGENT_E_SUCCESS on success, MISAGENT_E_INVALID_ARG when + * client is invalid, or an MISAGENT_E_* error code otherwise. + * ++ * @note This API call only works with iOS 9.2.1 or below. ++ * For newer iOS versions use misagent_copy_all() instead. ++ * + * @note If no provisioning profiles are installed on the device, this function + * still returns MISAGENT_E_SUCCESS and profiles will just point to an + * empty array. + */ + misagent_error_t misagent_copy(misagent_client_t client, plist_t* profiles); + ++/** ++ * Retrieves all installed provisioning profiles (iOS 9.3 or higher). ++ * ++ * @param client The connected misagent to use. ++ * @param profiles Pointer to a plist_t that will be set to a PLIST_ARRAY ++ * if the function is successful. ++ * ++ * @return MISAGENT_E_SUCCESS on success, MISAGENT_E_INVALID_ARG when ++ * client is invalid, or an MISAGENT_E_* error code otherwise. ++ * ++ * @note This API call only works with iOS 9.3 or higher. ++ * For older iOS versions use misagent_copy() instead. ++ * ++ * @note If no provisioning profiles are installed on the device, this function ++ * still returns MISAGENT_E_SUCCESS and profiles will just point to an ++ * empty array. ++ */ ++misagent_error_t misagent_copy_all(misagent_client_t client, plist_t* profiles); ++ + /** + * Removes a given provisioning profile. + * +diff --git a/src/misagent.c b/src/misagent.c +index 2dd3451..095edba 100644 +--- a/src/misagent.c ++++ b/src/misagent.c +@@ -202,6 +202,46 @@ LIBIMOBILEDEVICE_API misagent_error_t misagent_copy(misagent_client_t client, pl + + } + ++LIBIMOBILEDEVICE_API misagent_error_t misagent_copy_all(misagent_client_t client, plist_t* profiles) ++{ ++ if (!client || !client->parent || !profiles) ++ return MISAGENT_E_INVALID_ARG; ++ ++ client->last_error = MISAGENT_E_UNKNOWN_ERROR; ++ ++ plist_t dict = plist_new_dict(); ++ plist_dict_set_item(dict, "MessageType", plist_new_string("CopyAll")); ++ plist_dict_set_item(dict, "ProfileType", plist_new_string("Provisioning")); ++ ++ misagent_error_t res = misagent_error(property_list_service_send_xml_plist(client->parent, dict)); ++ plist_free(dict); ++ dict = NULL; ++ ++ if (res != MISAGENT_E_SUCCESS) { ++ debug_info("could not send plist, error %d", res); ++ return res; ++ } ++ ++ res = misagent_error(property_list_service_receive_plist(client->parent, &dict)); ++ if (res != MISAGENT_E_SUCCESS) { ++ debug_info("could not receive response, error %d", res); ++ return res; ++ } ++ if (!dict) { ++ debug_info("could not get response plist"); ++ return MISAGENT_E_UNKNOWN_ERROR; ++ } ++ ++ res = misagent_check_result(dict, &client->last_error); ++ if (res == MISAGENT_E_SUCCESS) { ++ *profiles = plist_copy(plist_dict_get_item(dict, "Payload")); ++ } ++ plist_free(dict); ++ ++ return res; ++ ++} ++ + LIBIMOBILEDEVICE_API misagent_error_t misagent_remove(misagent_client_t client, const char* profileID) + { + if (!client || !client->parent || !profileID) +-- +2.23.0 + + +From 76def2b68e7f2fbfc02315d29284fd74dabed8dc Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Thu, 1 Dec 2016 03:51:15 +0100 +Subject: [PATCH 043/151] ideviceprovision: Use newer API to get list of + profiles on iOS 9.3+ + +--- + tools/ideviceprovision.c | 32 ++++++++++++++++++++++++++++++-- + 1 file changed, 30 insertions(+), 2 deletions(-) + +diff --git a/tools/ideviceprovision.c b/tools/ideviceprovision.c +index 4915c05..77c27dc 100644 +--- a/tools/ideviceprovision.c ++++ b/tools/ideviceprovision.c +@@ -3,7 +3,7 @@ + * Simple utility to install, get, or remove provisioning profiles + * to/from idevices + * +- * Copyright (c) 2012 Nikias Bassen, All Rights Reserved. ++ * Copyright (c) 2012-2016 Nikias Bassen, All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public +@@ -390,6 +390,28 @@ int main(int argc, char *argv[]) + return -1; + } + ++ plist_t pver = NULL; ++ char *pver_s = NULL; ++ lockdownd_get_value(client, NULL, "ProductVersion", &pver); ++ if (pver && plist_get_node_type(pver) == PLIST_STRING) { ++ plist_get_string_val(pver, &pver_s); ++ } ++ plist_free(pver); ++ int product_version_major = 0; ++ int product_version_minor = 0; ++ int product_version_patch = 0; ++ if (pver_s) { ++ sscanf(pver_s, "%d.%d.%d", &product_version_major, &product_version_minor, &product_version_patch); ++ free(pver_s); ++ } ++ if (product_version_major == 0) { ++ fprintf(stderr, "ERROR: Could not determine the device's ProductVersion\n"); ++ lockdownd_client_free(client); ++ idevice_free(device); ++ return -1; ++ } ++ int product_version = ((product_version_major & 0xFF) << 16) | ((product_version_minor & 0xFF) << 8) | (product_version_patch & 0xFF); ++ + if (LOCKDOWN_E_SUCCESS != lockdownd_start_service(client, "com.apple.misagent", &service)) { + fprintf(stderr, "Could not start service \"com.apple.misagent\"\n"); + lockdownd_client_free(client); +@@ -437,7 +459,13 @@ int main(int argc, char *argv[]) + case OP_COPY: + { + plist_t profiles = NULL; +- if (misagent_copy(mis, &profiles) == MISAGENT_E_SUCCESS) { ++ misagent_error_t merr; ++ if (product_version < 0x090300) { ++ merr = misagent_copy(mis, &profiles); ++ } else { ++ merr = misagent_copy_all(mis, &profiles); ++ } ++ if (merr == MISAGENT_E_SUCCESS) { + uint32_t num_profiles = plist_array_get_size(profiles); + printf("Device has %d provisioning %s installed:\n", num_profiles, (num_profiles == 1) ? "profile" : "profiles"); + uint32_t j; +-- +2.23.0 + + +From 9083475cd899a09040b265863fcfee0b390c89b3 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Thu, 1 Dec 2016 03:52:16 +0100 +Subject: [PATCH 044/151] ideviceprovision: Check output directory parameter + for 'copy' command and return exit code on error + +--- + tools/ideviceprovision.c | 22 +++++++++++++--------- + 1 file changed, 13 insertions(+), 9 deletions(-) + +diff --git a/tools/ideviceprovision.c b/tools/ideviceprovision.c +index 77c27dc..7938580 100644 +--- a/tools/ideviceprovision.c ++++ b/tools/ideviceprovision.c +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + + #ifdef WIN32 + #include +@@ -254,6 +255,7 @@ int main(int argc, char *argv[]) + lockdownd_service_descriptor_t service = NULL; + idevice_t device = NULL; + idevice_error_t ret = IDEVICE_E_UNKNOWN_ERROR; ++ int res = 0; + int i; + int op = -1; + int output_xml = 0; +@@ -338,7 +340,6 @@ int main(int argc, char *argv[]) + } + + if (op == OP_DUMP) { +- int res = 0; + unsigned char* profile_data = NULL; + unsigned int profile_size = 0; + if (profile_read_from_file(param, &profile_data, &profile_size) != 0) { +@@ -372,6 +373,12 @@ int main(int argc, char *argv[]) + plist_free(pl); + + return res; ++ } else if (op == OP_COPY) { ++ struct stat st; ++ if ((stat(param, &st) < 0) || !S_ISDIR(st.st_mode)) { ++ fprintf(stderr, "ERROR: %s does not exist or is not a directory!\n", param); ++ return -1; ++ } + } + + ret = idevice_new(&device, udid); +@@ -502,19 +509,16 @@ int main(int argc, char *argv[]) + fclose(f); + printf(" => %s\n", pfname); + } else { +- fprintf(stderr, "Could not open '%s' for writing\n", pfname); ++ fprintf(stderr, "Could not open '%s' for writing: %s\n", pfname, strerror(errno)); + } + } +- if (p_uuid) { +- free(p_uuid); +- } +- if (p_name) { +- free(p_name); +- } ++ free(p_uuid); ++ free(p_name); + } + } else { + int sc = misagent_get_status_code(mis); + fprintf(stderr, "Could not get installed profiles from device, status code: 0x%x\n", sc); ++ res = -1; + } + } + break; +@@ -534,6 +538,6 @@ int main(int argc, char *argv[]) + + idevice_free(device); + +- return 0; ++ return res; + } + +-- +2.23.0 + + +From 9df4e695c55ddd319c5acaf7fa21f960afaa1e90 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Thu, 1 Dec 2016 03:56:00 +0100 +Subject: [PATCH 045/151] ideviceprovision: Allow copying single profiles + instead of all + +--- + tools/ideviceprovision.c | 38 ++++++++++++++++++++++++++++++++------ + 1 file changed, 32 insertions(+), 6 deletions(-) + +diff --git a/tools/ideviceprovision.c b/tools/ideviceprovision.c +index 7938580..79293bc 100644 +--- a/tools/ideviceprovision.c ++++ b/tools/ideviceprovision.c +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + #include + + #ifdef WIN32 +@@ -54,6 +55,9 @@ static void print_usage(int argc, char **argv) + printf(" copy PATH\tRetrieves all provisioning profiles from the device and\n"); + printf(" \tstores them into the existing directory specified by PATH.\n"); + printf(" \tThe files will be stored as UUID.mobileprovision\n"); ++ printf(" copy UUID PATH Retrieves the provisioning profile identified by UUID\n"); ++ printf(" \tfrom the device and stores it into the exisiting directory\n"); ++ printf(" \tspecified by PATH. The file will be stored as UUID.mobileprovision.\n"); + printf(" remove UUID\tRemoves the provisioning profile identified by UUID.\n"); + printf(" dump FILE\tPrints detailed information about the provisioning profile\n"); + printf(" \tspecified by FILE.\n\n"); +@@ -261,6 +265,7 @@ int main(int argc, char *argv[]) + int output_xml = 0; + const char* udid = NULL; + const char* param = NULL; ++ const char* param2 = NULL; + + /* parse cmdline args */ + for (i = 1; i < argc; i++) { +@@ -298,6 +303,10 @@ int main(int argc, char *argv[]) + } + param = argv[i]; + op = OP_COPY; ++ i++; ++ if (argv[i] && (strlen(argv[i]) > 0)) { ++ param2 = argv[i]; ++ } + continue; + } + else if (!strcmp(argv[i], "remove")) { +@@ -375,8 +384,9 @@ int main(int argc, char *argv[]) + return res; + } else if (op == OP_COPY) { + struct stat st; +- if ((stat(param, &st) < 0) || !S_ISDIR(st.st_mode)) { +- fprintf(stderr, "ERROR: %s does not exist or is not a directory!\n", param); ++ const char *checkdir = (param2) ? param2 : param; ++ if ((stat(checkdir, &st) < 0) || !S_ISDIR(st.st_mode)) { ++ fprintf(stderr, "ERROR: %s does not exist or is not a directory!\n", checkdir); + return -1; + } + } +@@ -473,10 +483,13 @@ int main(int argc, char *argv[]) + merr = misagent_copy_all(mis, &profiles); + } + if (merr == MISAGENT_E_SUCCESS) { ++ int found_match = 0; + uint32_t num_profiles = plist_array_get_size(profiles); +- printf("Device has %d provisioning %s installed:\n", num_profiles, (num_profiles == 1) ? "profile" : "profiles"); ++ if (op == OP_LIST || !param2) { ++ printf("Device has %d provisioning %s installed:\n", num_profiles, (num_profiles == 1) ? "profile" : "profiles"); ++ } + uint32_t j; +- for (j = 0; j < num_profiles; j++) { ++ for (j = 0; !found_match && j < num_profiles; j++) { + char* p_name = NULL; + char* p_uuid = NULL; + plist_t profile = plist_array_get_item(profiles, j); +@@ -492,13 +505,22 @@ int main(int argc, char *argv[]) + plist_get_string_val(node, &p_uuid); + } + } ++ if (param2) { ++ if (p_uuid && !strcmp(p_uuid, param)) { ++ found_match = 1; ++ } else { ++ free(p_uuid); ++ free(p_name); ++ continue; ++ } ++ } + printf("%s - %s\n", (p_uuid) ? p_uuid : "(unknown id)", (p_name) ? p_name : "(no name)"); + if (op == OP_COPY) { + char pfname[512]; + if (p_uuid) { +- sprintf(pfname, "%s/%s.mobileprovision", param, p_uuid); ++ sprintf(pfname, "%s/%s.mobileprovision", (param2) ? param2 : param, p_uuid); + } else { +- sprintf(pfname, "%s/profile%d.mobileprovision", param, j); ++ sprintf(pfname, "%s/profile%d.mobileprovision", (param2) ? param2 : param, j); + } + FILE* f = fopen(pfname, "wb"); + if (f) { +@@ -515,6 +537,10 @@ int main(int argc, char *argv[]) + free(p_uuid); + free(p_name); + } ++ if (param2 && !found_match) { ++ fprintf(stderr, "Profile '%s' was not found on the device.\n", param); ++ res = -1; ++ } + } else { + int sc = misagent_get_status_code(mis); + fprintf(stderr, "Could not get installed profiles from device, status code: 0x%x\n", sc); +-- +2.23.0 + + +From d936514291c0f65ecb0448f3a4aad1b40517f468 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Thu, 15 Dec 2016 02:39:37 +0100 +Subject: [PATCH 046/151] ideviceprovision: Add new remove-all command to + remove all installed profiles at once + +--- + tools/ideviceprovision.c | 65 +++++++++++++++++++++++++++++++++++++--- + 1 file changed, 61 insertions(+), 4 deletions(-) + +diff --git a/tools/ideviceprovision.c b/tools/ideviceprovision.c +index 79293bc..26ec418 100644 +--- a/tools/ideviceprovision.c ++++ b/tools/ideviceprovision.c +@@ -59,6 +59,7 @@ static void print_usage(int argc, char **argv) + printf(" \tfrom the device and stores it into the exisiting directory\n"); + printf(" \tspecified by PATH. The file will be stored as UUID.mobileprovision.\n"); + printf(" remove UUID\tRemoves the provisioning profile identified by UUID.\n"); ++ printf(" remove-all\tRemoves all installed provisioning profiles.\n"); + printf(" dump FILE\tPrints detailed information about the provisioning profile\n"); + printf(" \tspecified by FILE.\n\n"); + printf(" The following OPTIONS are accepted:\n"); +@@ -319,6 +320,11 @@ int main(int argc, char *argv[]) + op = OP_REMOVE; + continue; + } ++ else if (!strcmp(argv[i], "remove-all")) { ++ i++; ++ op = OP_REMOVE; ++ continue; ++ } + else if (!strcmp(argv[i], "dump")) { + i++; + if (!argv[i] || (strlen(argv[i]) < 1)) { +@@ -546,14 +552,65 @@ int main(int argc, char *argv[]) + fprintf(stderr, "Could not get installed profiles from device, status code: 0x%x\n", sc); + res = -1; + } ++ plist_free(profiles); + } + break; + case OP_REMOVE: +- if (misagent_remove(mis, param) == MISAGENT_E_SUCCESS) { +- printf("Profile '%s' removed.\n", param); ++ if (param) { ++ /* remove specified provisioning profile */ ++ if (misagent_remove(mis, param) == MISAGENT_E_SUCCESS) { ++ printf("Profile '%s' removed.\n", param); ++ } else { ++ int sc = misagent_get_status_code(mis); ++ fprintf(stderr, "Could not remove profile '%s', status code 0x%x\n", param, sc); ++ } + } else { +- int sc = misagent_get_status_code(mis); +- fprintf(stderr, "Could not remove profile '%s', status code 0x%x\n", param, sc); ++ /* remove all provisioning profiles */ ++ plist_t profiles = NULL; ++ misagent_error_t merr; ++ if (product_version < 0x090300) { ++ merr = misagent_copy(mis, &profiles); ++ } else { ++ merr = misagent_copy_all(mis, &profiles); ++ } ++ if (merr == MISAGENT_E_SUCCESS) { ++ uint32_t j; ++ uint32_t num_removed = 0; ++ for (j = 0; j < plist_array_get_size(profiles); j++) { ++ char* p_name = NULL; ++ char* p_uuid = NULL; ++ plist_t profile = plist_array_get_item(profiles, j); ++ plist_t pl = profile_get_embedded_plist(profile); ++ if (pl && (plist_get_node_type(pl) == PLIST_DICT)) { ++ plist_t node; ++ node = plist_dict_get_item(pl, "Name"); ++ if (node && (plist_get_node_type(node) == PLIST_STRING)) { ++ plist_get_string_val(node, &p_name); ++ } ++ node = plist_dict_get_item(pl, "UUID"); ++ if (node && (plist_get_node_type(node) == PLIST_STRING)) { ++ plist_get_string_val(node, &p_uuid); ++ } ++ } ++ if (p_uuid) { ++ if (misagent_remove(mis, p_uuid) == MISAGENT_E_SUCCESS) { ++ printf("OK profile removed: %s - %s\n", p_uuid, (p_name) ? p_name : "(no name)"); ++ num_removed++; ++ } else { ++ int sc = misagent_get_status_code(mis); ++ printf("FAIL profile not removed: %s - %s (status code 0x%x)\n", p_uuid, (p_name) ? p_name : "(no name)", sc); ++ } ++ } ++ free(p_name); ++ free(p_uuid); ++ } ++ printf("%d profiles removed.\n", num_removed); ++ } else { ++ int sc = misagent_get_status_code(mis); ++ fprintf(stderr, "Could not get installed profiles from device, status code: 0x%x\n", sc); ++ res = -1; ++ } ++ plist_free(profiles); + } + break; + default: +-- +2.23.0 + + +From c7f24a92f29180b50c0d92df34310f2179ba24cb Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Thu, 15 Dec 2016 02:57:31 +0100 +Subject: [PATCH 047/151] idevicebackup2: Fix logical bug when checking for + success of backup operation + +The condition in line 2278 is incorrectly evaluated when +mb2_status_check_snapshot_state() isn't able to read the Status.plist file. +While `if (-1) { ... }` will be a 'false' condition, `if (1 && -1) { ... }` +will be 'true' which in this case would make idevicebackup2 assume the backup +was successful while it was not. +This commit fixes this issue by changing the default return value of +mb2_status_check_snapshot_state() to be 0 (false). + +Thanks to Xiao Deng for pointing out this issue! +--- + tools/idevicebackup2.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/idevicebackup2.c b/tools/idevicebackup2.c +index 8dc32c5..e6c1d3f 100644 +--- a/tools/idevicebackup2.c ++++ b/tools/idevicebackup2.c +@@ -491,7 +491,7 @@ static plist_t mobilebackup_factory_info_plist_new(const char* udid, idevice_t d + + static int mb2_status_check_snapshot_state(const char *path, const char *udid, const char *matches) + { +- int ret = -1; ++ int ret = 0; + plist_t status_plist = NULL; + char *file_path = string_build_path(path, udid, "Status.plist", NULL); + +-- +2.23.0 + + +From 2b8313181fb52cecd1db20f11c0da0c2c169050a Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Wed, 21 Dec 2016 01:29:54 +0100 +Subject: [PATCH 048/151] cython: Make sure to pass correct CFLAGS for libplist + +--- + cython/Makefile.am | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/cython/Makefile.am b/cython/Makefile.am +index 94ff728..fb9a2e4 100644 +--- a/cython/Makefile.am ++++ b/cython/Makefile.am +@@ -1,6 +1,6 @@ + AM_CPPFLAGS = -I$(top_srcdir)/include + +-AM_CFLAGS = $(GLOBAL_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(openssl_CFLAGS) $(LFS_CFLAGS) ++AM_CFLAGS = $(GLOBAL_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(openssl_CFLAGS) $(libplist_CFLAGS) $(LFS_CFLAGS) + AM_LDFLAGS = $(libgnutls_LIBS) $(libtasn1_LIBS) $(openssl_LIBS) $(libplist_LIBS) + + if HAVE_CYTHON +-- +2.23.0 + + +From a80ba9363b4dc0ea1bcdad152cf2cdc974636ad6 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Thu, 22 Dec 2016 14:40:46 +0100 +Subject: [PATCH 049/151] ideviceprovision: Fix ASN1 parsing for large + provisioning profiles + +--- + tools/ideviceprovision.c | 47 ++++++++++++++++++++++++++++++---------- + 1 file changed, 35 insertions(+), 12 deletions(-) + +diff --git a/tools/ideviceprovision.c b/tools/ideviceprovision.c +index 26ec418..db00702 100644 +--- a/tools/ideviceprovision.c ++++ b/tools/ideviceprovision.c +@@ -87,30 +87,47 @@ enum { + + static void asn1_next_item(unsigned char** p) + { +- if (*(*p+1) & 0x80) { +- *p += 4; ++ char bsize = *(*p+1); ++ if (bsize & 0x80) { ++ *p += 2 + (bsize & 0xF); + } else { + *p += 3; + } + } + +-static int asn1_item_get_size(unsigned char* p) ++static size_t asn1_item_get_size(unsigned char* p) + { +- int res = 0; +- if (*(p+1) & 0x80) { ++ size_t res = 0; ++ char bsize = *(p+1); ++ if (bsize & 0x80) { + uint16_t ws = 0; +- memcpy(&ws, p+2, 2); +- ws = ntohs(ws); +- res = ws; ++ uint32_t ds = 0; ++ switch (bsize & 0xF) { ++ case 2: ++ ws = *(uint16_t*)(p+2); ++ res = ntohs(ws); ++ break; ++ case 3: ++ ds = *(uint32_t*)(p+2); ++ res = ntohl(ds) >> 8; ++ break; ++ case 4: ++ ds = *(uint32_t*)(p+2); ++ res = ntohl(ds); ++ break; ++ default: ++ fprintf(stderr, "ERROR: Invalid or unimplemented byte size %d\n", bsize & 0xF); ++ break; ++ } + } else { +- res = (int) *(p+1); ++ res = (int)bsize; + } + return res; + } + + static void asn1_skip_item(unsigned char** p) + { +- int sz = asn1_item_get_size(*p); ++ size_t sz = asn1_item_get_size(*p); + *p += 2; + *p += sz; + } +@@ -136,8 +153,14 @@ static plist_t profile_get_embedded_plist(plist_t profile) + fprintf(stderr, "%s: unexpected profile data (0)\n", __func__); + return NULL; + } +- uint16_t slen = asn1_item_get_size(pp); +- if (slen+4 != (uint16_t)blen) { ++ size_t slen = asn1_item_get_size(pp); ++ char bsize = *(pp+1); ++ if (bsize & 0x80) { ++ slen += 2 + bsize & 0xF; ++ } else { ++ slen += 3; ++ } ++ if (slen != blen) { + free(bbuf); + fprintf(stderr, "%s: unexpected profile data (1)\n", __func__); + return NULL; +-- +2.23.0 + + +From 038bb5902fcc4e981fb349fbba629eab2bdf93ff Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Sat, 31 Dec 2016 02:59:36 +0100 +Subject: [PATCH 050/151] Add ax_pthread.m4 for proper pthread cflags/ldflags + +--- + configure.ac | 18 +- + m4/ax_pthread.m4 | 485 +++++++++++++++++++++++++++++++++++++++++++++++ + src/Makefile.am | 4 +- + 3 files changed, 495 insertions(+), 12 deletions(-) + create mode 100644 m4/ax_pthread.m4 + +diff --git a/configure.ac b/configure.ac +index 26fe819..e41baa3 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -66,25 +66,23 @@ if test "x$ac_cv_have_endian_h" = "xno"; then + fi + + # Check for operating system +-AC_MSG_CHECKING([whether to enable WIN32 build settings]) ++AC_MSG_CHECKING([whether we need platform-specific build settings]) + case ${host_os} in + *mingw32*|*cygwin*) +- win32=true + AC_MSG_RESULT([yes]) +- AC_CHECK_TOOL([WINDRES], [windres], AC_MSG_ERROR([windres not found])) +- AC_SUBST(WINDRES) ++ win32=true + ;; +- *) +- win32=false ++ darwin*) + AC_MSG_RESULT([no]) + ;; ++ *) ++ AC_MSG_RESULT([yes]) ++ AX_PTHREAD([], [AC_MSG_ERROR([pthread is required to build $PACKAGE_NAME])]) ++ AC_CHECK_LIB(pthread, [pthread_once], [], [AC_MSG_ERROR([pthread with pthread_once required to build $PACKAGE_NAME])]) ++ ;; + esac + AM_CONDITIONAL(WIN32, test x$win32 = xtrue) + +-if test "x$win32" != xtrue; then +- AC_CHECK_LIB(pthread, [pthread_create, pthread_mutex_lock], [AC_SUBST(libpthread_LIBS,[-lpthread])], [AC_MSG_ERROR([libpthread is required to build libimobiledevice])]) +-fi +- + # Cython Python Bindings + AC_ARG_WITH([cython], + [AS_HELP_STRING([--without-cython], +diff --git a/m4/ax_pthread.m4 b/m4/ax_pthread.m4 +new file mode 100644 +index 0000000..4c4051e +--- /dev/null ++++ b/m4/ax_pthread.m4 +@@ -0,0 +1,485 @@ ++# =========================================================================== ++# http://www.gnu.org/software/autoconf-archive/ax_pthread.html ++# =========================================================================== ++# ++# SYNOPSIS ++# ++# AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) ++# ++# DESCRIPTION ++# ++# This macro figures out how to build C programs using POSIX threads. It ++# sets the PTHREAD_LIBS output variable to the threads library and linker ++# flags, and the PTHREAD_CFLAGS output variable to any special C compiler ++# flags that are needed. (The user can also force certain compiler ++# flags/libs to be tested by setting these environment variables.) ++# ++# Also sets PTHREAD_CC to any special C compiler that is needed for ++# multi-threaded programs (defaults to the value of CC otherwise). (This ++# is necessary on AIX to use the special cc_r compiler alias.) ++# ++# NOTE: You are assumed to not only compile your program with these flags, ++# but also to link with them as well. For example, you might link with ++# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS ++# ++# If you are only building threaded programs, you may wish to use these ++# variables in your default LIBS, CFLAGS, and CC: ++# ++# LIBS="$PTHREAD_LIBS $LIBS" ++# CFLAGS="$CFLAGS $PTHREAD_CFLAGS" ++# CC="$PTHREAD_CC" ++# ++# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant ++# has a nonstandard name, this macro defines PTHREAD_CREATE_JOINABLE to ++# that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX). ++# ++# Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the ++# PTHREAD_PRIO_INHERIT symbol is defined when compiling with ++# PTHREAD_CFLAGS. ++# ++# ACTION-IF-FOUND is a list of shell commands to run if a threads library ++# is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it ++# is not found. If ACTION-IF-FOUND is not specified, the default action ++# will define HAVE_PTHREAD. ++# ++# Please let the authors know if this macro fails on any platform, or if ++# you have any other suggestions or comments. This macro was based on work ++# by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help ++# from M. Frigo), as well as ac_pthread and hb_pthread macros posted by ++# Alejandro Forero Cuervo to the autoconf macro repository. We are also ++# grateful for the helpful feedback of numerous users. ++# ++# Updated for Autoconf 2.68 by Daniel Richard G. ++# ++# LICENSE ++# ++# Copyright (c) 2008 Steven G. Johnson ++# Copyright (c) 2011 Daniel Richard G. ++# ++# This program is free software: you can redistribute it and/or modify it ++# under the terms of the GNU General Public License as published by the ++# Free Software Foundation, either version 3 of the License, or (at your ++# option) any later version. ++# ++# This program is distributed in the hope that it will be useful, but ++# WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General ++# Public License for more details. ++# ++# You should have received a copy of the GNU General Public License along ++# with this program. If not, see . ++# ++# As a special exception, the respective Autoconf Macro's copyright owner ++# gives unlimited permission to copy, distribute and modify the configure ++# scripts that are the output of Autoconf when processing the Macro. You ++# need not follow the terms of the GNU General Public License when using ++# or distributing such scripts, even though portions of the text of the ++# Macro appear in them. The GNU General Public License (GPL) does govern ++# all other use of the material that constitutes the Autoconf Macro. ++# ++# This special exception to the GPL applies to versions of the Autoconf ++# Macro released by the Autoconf Archive. When you make and distribute a ++# modified version of the Autoconf Macro, you may extend this special ++# exception to the GPL to apply to your modified version as well. ++ ++#serial 23 ++ ++AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD]) ++AC_DEFUN([AX_PTHREAD], [ ++AC_REQUIRE([AC_CANONICAL_HOST]) ++AC_REQUIRE([AC_PROG_CC]) ++AC_REQUIRE([AC_PROG_SED]) ++AC_LANG_PUSH([C]) ++ax_pthread_ok=no ++ ++# We used to check for pthread.h first, but this fails if pthread.h ++# requires special compiler flags (e.g. on Tru64 or Sequent). ++# It gets checked for in the link test anyway. ++ ++# First of all, check if the user has set any of the PTHREAD_LIBS, ++# etcetera environment variables, and if threads linking works using ++# them: ++if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then ++ ax_pthread_save_CC="$CC" ++ ax_pthread_save_CFLAGS="$CFLAGS" ++ ax_pthread_save_LIBS="$LIBS" ++ AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"]) ++ CFLAGS="$CFLAGS $PTHREAD_CFLAGS" ++ LIBS="$PTHREAD_LIBS $LIBS" ++ AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS]) ++ AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_join])], [ax_pthread_ok=yes]) ++ AC_MSG_RESULT([$ax_pthread_ok]) ++ if test "x$ax_pthread_ok" = "xno"; then ++ PTHREAD_LIBS="" ++ PTHREAD_CFLAGS="" ++ fi ++ CC="$ax_pthread_save_CC" ++ CFLAGS="$ax_pthread_save_CFLAGS" ++ LIBS="$ax_pthread_save_LIBS" ++fi ++ ++# We must check for the threads library under a number of different ++# names; the ordering is very important because some systems ++# (e.g. DEC) have both -lpthread and -lpthreads, where one of the ++# libraries is broken (non-POSIX). ++ ++# Create a list of thread flags to try. Items starting with a "-" are ++# C compiler flags, and other items are library names, except for "none" ++# which indicates that we try without any flags at all, and "pthread-config" ++# which is a program returning the flags for the Pth emulation library. ++ ++ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" ++ ++# The ordering *is* (sometimes) important. Some notes on the ++# individual items follow: ++ ++# pthreads: AIX (must check this before -lpthread) ++# none: in case threads are in libc; should be tried before -Kthread and ++# other compiler flags to prevent continual compiler warnings ++# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) ++# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64 ++# (Note: HP C rejects this with "bad form for `-t' option") ++# -pthreads: Solaris/gcc (Note: HP C also rejects) ++# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it ++# doesn't hurt to check since this sometimes defines pthreads and ++# -D_REENTRANT too), HP C (must be checked before -lpthread, which ++# is present but should not be used directly; and before -mthreads, ++# because the compiler interprets this as "-mt" + "-hreads") ++# -mthreads: Mingw32/gcc, Lynx/gcc ++# pthread: Linux, etcetera ++# --thread-safe: KAI C++ ++# pthread-config: use pthread-config program (for GNU Pth library) ++ ++case $host_os in ++ ++ freebsd*) ++ ++ # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) ++ # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) ++ ++ ax_pthread_flags="-kthread lthread $ax_pthread_flags" ++ ;; ++ ++ hpux*) ++ ++ # From the cc(1) man page: "[-mt] Sets various -D flags to enable ++ # multi-threading and also sets -lpthread." ++ ++ ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags" ++ ;; ++ ++ openedition*) ++ ++ # IBM z/OS requires a feature-test macro to be defined in order to ++ # enable POSIX threads at all, so give the user a hint if this is ++ # not set. (We don't define these ourselves, as they can affect ++ # other portions of the system API in unpredictable ways.) ++ ++ AC_EGREP_CPP([AX_PTHREAD_ZOS_MISSING], ++ [ ++# if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS) ++ AX_PTHREAD_ZOS_MISSING ++# endif ++ ], ++ [AC_MSG_WARN([IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support.])]) ++ ;; ++ ++ solaris*) ++ ++ # On Solaris (at least, for some versions), libc contains stubbed ++ # (non-functional) versions of the pthreads routines, so link-based ++ # tests will erroneously succeed. (N.B.: The stubs are missing ++ # pthread_cleanup_push, or rather a function called by this macro, ++ # so we could check for that, but who knows whether they'll stub ++ # that too in a future libc.) So we'll check first for the ++ # standard Solaris way of linking pthreads (-mt -lpthread). ++ ++ ax_pthread_flags="-mt,pthread pthread $ax_pthread_flags" ++ ;; ++esac ++ ++# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC) ++ ++AS_IF([test "x$GCC" = "xyes"], ++ [ax_pthread_flags="-pthread -pthreads $ax_pthread_flags"]) ++ ++# The presence of a feature test macro requesting re-entrant function ++# definitions is, on some systems, a strong hint that pthreads support is ++# correctly enabled ++ ++case $host_os in ++ darwin* | hpux* | linux* | osf* | solaris*) ++ ax_pthread_check_macro="_REENTRANT" ++ ;; ++ ++ aix*) ++ ax_pthread_check_macro="_THREAD_SAFE" ++ ;; ++ ++ *) ++ ax_pthread_check_macro="--" ++ ;; ++esac ++AS_IF([test "x$ax_pthread_check_macro" = "x--"], ++ [ax_pthread_check_cond=0], ++ [ax_pthread_check_cond="!defined($ax_pthread_check_macro)"]) ++ ++# Are we compiling with Clang? ++ ++AC_CACHE_CHECK([whether $CC is Clang], ++ [ax_cv_PTHREAD_CLANG], ++ [ax_cv_PTHREAD_CLANG=no ++ # Note that Autoconf sets GCC=yes for Clang as well as GCC ++ if test "x$GCC" = "xyes"; then ++ AC_EGREP_CPP([AX_PTHREAD_CC_IS_CLANG], ++ [/* Note: Clang 2.7 lacks __clang_[a-z]+__ */ ++# if defined(__clang__) && defined(__llvm__) ++ AX_PTHREAD_CC_IS_CLANG ++# endif ++ ], ++ [ax_cv_PTHREAD_CLANG=yes]) ++ fi ++ ]) ++ax_pthread_clang="$ax_cv_PTHREAD_CLANG" ++ ++ax_pthread_clang_warning=no ++ ++# Clang needs special handling, because older versions handle the -pthread ++# option in a rather... idiosyncratic way ++ ++if test "x$ax_pthread_clang" = "xyes"; then ++ ++ # Clang takes -pthread; it has never supported any other flag ++ ++ # (Note 1: This will need to be revisited if a system that Clang ++ # supports has POSIX threads in a separate library. This tends not ++ # to be the way of modern systems, but it's conceivable.) ++ ++ # (Note 2: On some systems, notably Darwin, -pthread is not needed ++ # to get POSIX threads support; the API is always present and ++ # active. We could reasonably leave PTHREAD_CFLAGS empty. But ++ # -pthread does define _REENTRANT, and while the Darwin headers ++ # ignore this macro, third-party headers might not.) ++ ++ PTHREAD_CFLAGS="-pthread" ++ PTHREAD_LIBS= ++ ++ ax_pthread_ok=yes ++ ++ # However, older versions of Clang make a point of warning the user ++ # that, in an invocation where only linking and no compilation is ++ # taking place, the -pthread option has no effect ("argument unused ++ # during compilation"). They expect -pthread to be passed in only ++ # when source code is being compiled. ++ # ++ # Problem is, this is at odds with the way Automake and most other ++ # C build frameworks function, which is that the same flags used in ++ # compilation (CFLAGS) are also used in linking. Many systems ++ # supported by AX_PTHREAD require exactly this for POSIX threads ++ # support, and in fact it is often not straightforward to specify a ++ # flag that is used only in the compilation phase and not in ++ # linking. Such a scenario is extremely rare in practice. ++ # ++ # Even though use of the -pthread flag in linking would only print ++ # a warning, this can be a nuisance for well-run software projects ++ # that build with -Werror. So if the active version of Clang has ++ # this misfeature, we search for an option to squash it. ++ ++ AC_CACHE_CHECK([whether Clang needs flag to prevent "argument unused" warning when linking with -pthread], ++ [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG], ++ [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown ++ # Create an alternate version of $ac_link that compiles and ++ # links in two steps (.c -> .o, .o -> exe) instead of one ++ # (.c -> exe), because the warning occurs only in the second ++ # step ++ ax_pthread_save_ac_link="$ac_link" ++ ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g' ++ ax_pthread_link_step=`$as_echo "$ac_link" | sed "$ax_pthread_sed"` ++ ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)" ++ ax_pthread_save_CFLAGS="$CFLAGS" ++ for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do ++ AS_IF([test "x$ax_pthread_try" = "xunknown"], [break]) ++ CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS" ++ ac_link="$ax_pthread_save_ac_link" ++ AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], ++ [ac_link="$ax_pthread_2step_ac_link" ++ AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], ++ [break]) ++ ]) ++ done ++ ac_link="$ax_pthread_save_ac_link" ++ CFLAGS="$ax_pthread_save_CFLAGS" ++ AS_IF([test "x$ax_pthread_try" = "x"], [ax_pthread_try=no]) ++ ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try" ++ ]) ++ ++ case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in ++ no | unknown) ;; ++ *) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;; ++ esac ++ ++fi # $ax_pthread_clang = yes ++ ++if test "x$ax_pthread_ok" = "xno"; then ++for ax_pthread_try_flag in $ax_pthread_flags; do ++ ++ case $ax_pthread_try_flag in ++ none) ++ AC_MSG_CHECKING([whether pthreads work without any flags]) ++ ;; ++ ++ -mt,pthread) ++ AC_MSG_CHECKING([whether pthreads work with -mt -lpthread]) ++ PTHREAD_CFLAGS="-mt" ++ PTHREAD_LIBS="-lpthread" ++ ;; ++ ++ -*) ++ AC_MSG_CHECKING([whether pthreads work with $ax_pthread_try_flag]) ++ PTHREAD_CFLAGS="$ax_pthread_try_flag" ++ ;; ++ ++ pthread-config) ++ AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no]) ++ AS_IF([test "x$ax_pthread_config" = "xno"], [continue]) ++ PTHREAD_CFLAGS="`pthread-config --cflags`" ++ PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" ++ ;; ++ ++ *) ++ AC_MSG_CHECKING([for the pthreads library -l$ax_pthread_try_flag]) ++ PTHREAD_LIBS="-l$ax_pthread_try_flag" ++ ;; ++ esac ++ ++ ax_pthread_save_CFLAGS="$CFLAGS" ++ ax_pthread_save_LIBS="$LIBS" ++ CFLAGS="$CFLAGS $PTHREAD_CFLAGS" ++ LIBS="$PTHREAD_LIBS $LIBS" ++ ++ # Check for various functions. We must include pthread.h, ++ # since some functions may be macros. (On the Sequent, we ++ # need a special flag -Kthread to make this header compile.) ++ # We check for pthread_join because it is in -lpthread on IRIX ++ # while pthread_create is in libc. We check for pthread_attr_init ++ # due to DEC craziness with -lpthreads. We check for ++ # pthread_cleanup_push because it is one of the few pthread ++ # functions on Solaris that doesn't have a non-functional libc stub. ++ # We try pthread_create on general principles. ++ ++ AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ++# if $ax_pthread_check_cond ++# error "$ax_pthread_check_macro must be defined" ++# endif ++ static void routine(void *a) { a = 0; } ++ static void *start_routine(void *a) { return a; }], ++ [pthread_t th; pthread_attr_t attr; ++ pthread_create(&th, 0, start_routine, 0); ++ pthread_join(th, 0); ++ pthread_attr_init(&attr); ++ pthread_cleanup_push(routine, 0); ++ pthread_cleanup_pop(0) /* ; */])], ++ [ax_pthread_ok=yes], ++ []) ++ ++ CFLAGS="$ax_pthread_save_CFLAGS" ++ LIBS="$ax_pthread_save_LIBS" ++ ++ AC_MSG_RESULT([$ax_pthread_ok]) ++ AS_IF([test "x$ax_pthread_ok" = "xyes"], [break]) ++ ++ PTHREAD_LIBS="" ++ PTHREAD_CFLAGS="" ++done ++fi ++ ++# Various other checks: ++if test "x$ax_pthread_ok" = "xyes"; then ++ ax_pthread_save_CFLAGS="$CFLAGS" ++ ax_pthread_save_LIBS="$LIBS" ++ CFLAGS="$CFLAGS $PTHREAD_CFLAGS" ++ LIBS="$PTHREAD_LIBS $LIBS" ++ ++ # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. ++ AC_CACHE_CHECK([for joinable pthread attribute], ++ [ax_cv_PTHREAD_JOINABLE_ATTR], ++ [ax_cv_PTHREAD_JOINABLE_ATTR=unknown ++ for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do ++ AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], ++ [int attr = $ax_pthread_attr; return attr /* ; */])], ++ [ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break], ++ []) ++ done ++ ]) ++ AS_IF([test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \ ++ test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \ ++ test "x$ax_pthread_joinable_attr_defined" != "xyes"], ++ [AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE], ++ [$ax_cv_PTHREAD_JOINABLE_ATTR], ++ [Define to necessary symbol if this constant ++ uses a non-standard name on your system.]) ++ ax_pthread_joinable_attr_defined=yes ++ ]) ++ ++ AC_CACHE_CHECK([whether more special flags are required for pthreads], ++ [ax_cv_PTHREAD_SPECIAL_FLAGS], ++ [ax_cv_PTHREAD_SPECIAL_FLAGS=no ++ case $host_os in ++ solaris*) ++ ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS" ++ ;; ++ esac ++ ]) ++ AS_IF([test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \ ++ test "x$ax_pthread_special_flags_added" != "xyes"], ++ [PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS" ++ ax_pthread_special_flags_added=yes]) ++ ++ AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT], ++ [ax_cv_PTHREAD_PRIO_INHERIT], ++ [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], ++ [[int i = PTHREAD_PRIO_INHERIT;]])], ++ [ax_cv_PTHREAD_PRIO_INHERIT=yes], ++ [ax_cv_PTHREAD_PRIO_INHERIT=no]) ++ ]) ++ AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \ ++ test "x$ax_pthread_prio_inherit_defined" != "xyes"], ++ [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.]) ++ ax_pthread_prio_inherit_defined=yes ++ ]) ++ ++ CFLAGS="$ax_pthread_save_CFLAGS" ++ LIBS="$ax_pthread_save_LIBS" ++ ++ # More AIX lossage: compile with *_r variant ++ if test "x$GCC" != "xyes"; then ++ case $host_os in ++ aix*) ++ AS_CASE(["x/$CC"], ++ [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6], ++ [#handle absolute path differently from PATH based program lookup ++ AS_CASE(["x$CC"], ++ [x/*], ++ [AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])], ++ [AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])]) ++ ;; ++ esac ++ fi ++fi ++ ++test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" ++ ++AC_SUBST([PTHREAD_LIBS]) ++AC_SUBST([PTHREAD_CFLAGS]) ++AC_SUBST([PTHREAD_CC]) ++ ++# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: ++if test "x$ax_pthread_ok" = "xyes"; then ++ ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1]) ++ : ++else ++ ax_pthread_ok=no ++ $2 ++fi ++AC_LANG_POP ++])dnl AX_PTHREAD +diff --git a/src/Makefile.am b/src/Makefile.am +index 5ced544..efd95eb 100644 +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -1,7 +1,7 @@ + AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir) + +-AM_CFLAGS = $(GLOBAL_CFLAGS) $(libusbmuxd_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(libplist_CFLAGS) $(LFS_CFLAGS) $(openssl_CFLAGS) +-AM_LDFLAGS = $(libgnutls_LIBS) $(libtasn1_LIBS) $(libplist_LIBS) $(libusbmuxd_LIBS) $(libgcrypt_LIBS) $(libpthread_LIBS) $(openssl_LIBS) ++AM_CFLAGS = $(GLOBAL_CFLAGS) $(libusbmuxd_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(libplist_CFLAGS) $(LFS_CFLAGS) $(openssl_CFLAGS) $(PTHREAD_CFLAGS) ++AM_LDFLAGS = $(libgnutls_LIBS) $(libtasn1_LIBS) $(libplist_LIBS) $(libusbmuxd_LIBS) $(libgcrypt_LIBS) $(openssl_LIBS) $(PTHREAD_LIBS) + + lib_LTLIBRARIES = libimobiledevice.la + libimobiledevice_la_LIBADD = $(top_builddir)/common/libinternalcommon.la +-- +2.23.0 + + +From b78a42e0531d219e27f5c57350886bc7c14d4684 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Wed, 4 Jan 2017 20:28:59 +0100 +Subject: [PATCH 051/151] ideviceprovision: Silence compiler warning (missing + parenthesis) + +--- + tools/ideviceprovision.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/ideviceprovision.c b/tools/ideviceprovision.c +index db00702..0bef7e8 100644 +--- a/tools/ideviceprovision.c ++++ b/tools/ideviceprovision.c +@@ -156,7 +156,7 @@ static plist_t profile_get_embedded_plist(plist_t profile) + size_t slen = asn1_item_get_size(pp); + char bsize = *(pp+1); + if (bsize & 0x80) { +- slen += 2 + bsize & 0xF; ++ slen += 2 + (bsize & 0xF); + } else { + slen += 3; + } +-- +2.23.0 + + +From 45fda819e1aae3cacf25a04b9fe22cd6ddc61f5a Mon Sep 17 00:00:00 2001 +From: Antoine Reversat +Date: Tue, 10 Jan 2017 09:55:15 -0800 +Subject: [PATCH 052/151] property_list_service: Remove packet length check + when receiving plist data + +There are services that would send really large plist data, e.g. when listing +provisioning profiles. Instead of forcing the data to be less than 16MB we +try to allocate a buffer as large as requested. If the allocation fails the +function returns with an error. +--- + src/property_list_service.c | 89 ++++++++++++++++++------------------- + 1 file changed, 43 insertions(+), 46 deletions(-) + +diff --git a/src/property_list_service.c b/src/property_list_service.c +index 141fab7..a5bdf9b 100644 +--- a/src/property_list_service.c ++++ b/src/property_list_service.c +@@ -193,59 +193,56 @@ static property_list_service_error_t internal_plist_receive_timeout(property_lis + debug_info("initial read failed!"); + return PROPERTY_LIST_SERVICE_E_MUX_ERROR; + } else { ++ uint32_t curlen = 0; ++ char *content = NULL; ++ + pktlen = be32toh(pktlen); +- if (pktlen < (1 << 24)) { /* prevent huge buffers */ +- uint32_t curlen = 0; +- char *content = NULL; +- debug_info("%d bytes following", pktlen); +- content = (char*)malloc(pktlen); +- if (!content) { +- debug_info("out of memory when allocating %d bytes", pktlen); +- return PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR; +- } ++ debug_info("%d bytes following", pktlen); ++ content = (char*)malloc(pktlen); ++ if (!content) { ++ debug_info("out of memory when allocating %d bytes", pktlen); ++ return PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR; ++ } + +- while (curlen < pktlen) { +- service_receive(client->parent, content+curlen, pktlen-curlen, &bytes); +- if (bytes <= 0) { +- res = PROPERTY_LIST_SERVICE_E_MUX_ERROR; +- break; +- } +- debug_info("received %d bytes", bytes); +- curlen += bytes; +- } +- if (curlen < pktlen) { +- debug_info("received incomplete packet (%d of %d bytes)", curlen, pktlen); +- if (curlen > 0) { +- debug_info("incomplete packet following:"); +- debug_buffer(content, curlen); +- } +- free(content); +- return res; ++ while (curlen < pktlen) { ++ service_receive(client->parent, content+curlen, pktlen-curlen, &bytes); ++ if (bytes <= 0) { ++ res = PROPERTY_LIST_SERVICE_E_MUX_ERROR; ++ break; + } +- if ((pktlen > 8) && !memcmp(content, "bplist00", 8)) { +- plist_from_bin(content, pktlen, plist); +- } else if ((pktlen > 5) && !memcmp(content, "= 0) && (content[bytes] < 0x20) && (content[bytes] != 0x09) && (content[bytes] != 0x0a) && (content[bytes] != 0x0d)) +- content[bytes] = 0x20; +- } +- plist_from_xml(content, pktlen, plist); +- } else { +- debug_info("WARNING: received unexpected non-plist content"); +- debug_buffer(content, pktlen); +- } +- if (*plist) { +- debug_plist(*plist); +- res = PROPERTY_LIST_SERVICE_E_SUCCESS; +- } else { +- res = PROPERTY_LIST_SERVICE_E_PLIST_ERROR; ++ debug_info("received %d bytes", bytes); ++ curlen += bytes; ++ } ++ if (curlen < pktlen) { ++ debug_info("received incomplete packet (%d of %d bytes)", curlen, pktlen); ++ if (curlen > 0) { ++ debug_info("incomplete packet following:"); ++ debug_buffer(content, curlen); + } + free(content); +- content = NULL; ++ return res; ++ } ++ if ((pktlen > 8) && !memcmp(content, "bplist00", 8)) { ++ plist_from_bin(content, pktlen, plist); ++ } else if ((pktlen > 5) && !memcmp(content, "= 0) && (content[bytes] < 0x20) && (content[bytes] != 0x09) && (content[bytes] != 0x0a) && (content[bytes] != 0x0d)) ++ content[bytes] = 0x20; ++ } ++ plist_from_xml(content, pktlen, plist); ++ } else { ++ debug_info("WARNING: received unexpected non-plist content"); ++ debug_buffer(content, pktlen); ++ } ++ if (*plist) { ++ debug_plist(*plist); ++ res = PROPERTY_LIST_SERVICE_E_SUCCESS; + } else { +- res = PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR; ++ res = PROPERTY_LIST_SERVICE_E_PLIST_ERROR; + } ++ free(content); ++ content = NULL; + } + return res; + } +-- +2.23.0 + + +From 5a8449a391d2cc848f55cfb4406bad4ded0bd138 Mon Sep 17 00:00:00 2001 +From: BALATON Zoltan +Date: Tue, 12 Jul 2016 23:01:47 +0200 +Subject: [PATCH 053/151] Propagate lower level errors to callers instead of + returning unknown error for most failures + +--- + include/libimobiledevice/lockdown.h | 2 +- + src/idevice.c | 4 +- + src/lockdown.c | 76 +++++++++++++++-------------- + src/property_list_service.c | 4 +- + 4 files changed, 46 insertions(+), 40 deletions(-) + +diff --git a/include/libimobiledevice/lockdown.h b/include/libimobiledevice/lockdown.h +index 0e48eef..b5c126c 100644 +--- a/include/libimobiledevice/lockdown.h ++++ b/include/libimobiledevice/lockdown.h +@@ -43,7 +43,7 @@ typedef enum { + LOCKDOWN_E_PAIRING_FAILED = -4, + LOCKDOWN_E_SSL_ERROR = -5, + LOCKDOWN_E_DICT_ERROR = -6, +- LOCKDOWN_E_NOT_ENOUGH_DATA = -7, ++ LOCKDOWN_E_RECEIVE_TIMEOUT = -7, + LOCKDOWN_E_MUX_ERROR = -8, + LOCKDOWN_E_NO_RUNNING_SESSION = -9, + /* native */ +diff --git a/src/idevice.c b/src/idevice.c +index b6dfe4e..913038e 100644 +--- a/src/idevice.c ++++ b/src/idevice.c +@@ -376,8 +376,8 @@ static idevice_error_t internal_connection_receive_timeout(idevice_connection_t + if (connection->type == CONNECTION_USBMUXD) { + int res = usbmuxd_recv_timeout((int)(long)connection->data, data, len, recv_bytes, timeout); + if (res < 0) { +- debug_info("ERROR: usbmuxd_recv_timeout returned %d (%s)", res, strerror(-res)); +- return IDEVICE_E_UNKNOWN_ERROR; ++ debug_info("ERROR: usbmuxd_recv_timeout returned %d (%s)", res, strerror(errno)); ++ return (res == -EAGAIN ? IDEVICE_E_NOT_ENOUGH_DATA : IDEVICE_E_UNKNOWN_ERROR); + } + return IDEVICE_E_SUCCESS; + } else { +diff --git a/src/lockdown.c b/src/lockdown.c +index cae950b..5251737 100644 +--- a/src/lockdown.c ++++ b/src/lockdown.c +@@ -135,6 +135,36 @@ static lockdownd_error_t lockdownd_strtoerr(const char* name) + return err; + } + ++/** ++ * Convert a property_list_service_error_t value to a lockdownd_error_t ++ * value. Used internally to get correct error codes. ++ * ++ * @param err A property_list_service_error_t error code ++ * ++ * @return A matching lockdownd_error_t error code, ++ * LOCKDOWND_E_UNKNOWN_ERROR otherwise. ++ */ ++static lockdownd_error_t lockdownd_error(property_list_service_error_t err) ++{ ++ switch (err) { ++ case PROPERTY_LIST_SERVICE_E_SUCCESS: ++ return LOCKDOWN_E_SUCCESS; ++ case PROPERTY_LIST_SERVICE_E_INVALID_ARG: ++ return LOCKDOWN_E_INVALID_ARG; ++ case PROPERTY_LIST_SERVICE_E_PLIST_ERROR: ++ return LOCKDOWN_E_PLIST_ERROR; ++ case PROPERTY_LIST_SERVICE_E_MUX_ERROR: ++ return LOCKDOWN_E_MUX_ERROR; ++ case PROPERTY_LIST_SERVICE_E_SSL_ERROR: ++ return LOCKDOWN_E_SSL_ERROR; ++ case PROPERTY_LIST_SERVICE_E_RECEIVE_TIMEOUT: ++ return LOCKDOWN_E_RECEIVE_TIMEOUT; ++ default: ++ break; ++ } ++ return LOCKDOWN_E_UNKNOWN_ERROR; ++} ++ + /** + * Internally used function for checking the result from lockdown's answer + * plist to a previously sent request. +@@ -349,18 +379,8 @@ LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_receive(lockdownd_client_t clie + { + if (!client || !plist || (plist && *plist)) + return LOCKDOWN_E_INVALID_ARG; +- lockdownd_error_t ret = LOCKDOWN_E_SUCCESS; +- property_list_service_error_t err; +- +- err = property_list_service_receive_plist(client->parent, plist); +- if (err != PROPERTY_LIST_SERVICE_E_SUCCESS) { +- ret = LOCKDOWN_E_UNKNOWN_ERROR; +- } + +- if (!*plist) +- ret = LOCKDOWN_E_PLIST_ERROR; +- +- return ret; ++ return lockdownd_error(property_list_service_receive_plist(client->parent, plist)); + } + + LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_send(lockdownd_client_t client, plist_t plist) +@@ -368,14 +388,7 @@ LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_send(lockdownd_client_t client, + if (!client || !plist) + return LOCKDOWN_E_INVALID_ARG; + +- lockdownd_error_t ret = LOCKDOWN_E_SUCCESS; +- property_list_service_error_t err; +- +- err = property_list_service_send_xml_plist(client->parent, plist); +- if (err != PROPERTY_LIST_SERVICE_E_SUCCESS) { +- ret = LOCKDOWN_E_UNKNOWN_ERROR; +- } +- return ret; ++ return lockdownd_error(property_list_service_send_xml_plist(client->parent, plist)); + } + + LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_query_type(lockdownd_client_t client, char **type) +@@ -686,13 +699,11 @@ LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_client_new_with_handshake(idevi + } + + /* perform handshake */ +- if (LOCKDOWN_E_SUCCESS != lockdownd_query_type(client_loc, &type)) { ++ ret = lockdownd_query_type(client_loc, &type); ++ if (LOCKDOWN_E_SUCCESS != ret) { + debug_info("QueryType failed in the lockdownd client."); +- ret = LOCKDOWN_E_NOT_ENOUGH_DATA; +- } else { +- if (strcmp("com.apple.mobile.lockdown", type)) { +- debug_info("Warning QueryType request returned \"%s\".", type); +- } ++ } else if (strcmp("com.apple.mobile.lockdown", type)) { ++ debug_info("Warning QueryType request returned \"%s\".", type); + } + free(type); + +@@ -1113,7 +1124,6 @@ LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_goodbye(lockdownd_client_t clie + LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_start_session(lockdownd_client_t client, const char *host_id, char **session_id, int *ssl_enabled) + { + lockdownd_error_t ret = LOCKDOWN_E_SUCCESS; +- property_list_service_error_t plret; + plist_t dict = NULL; + + if (!client || !host_id) +@@ -1184,20 +1194,14 @@ LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_start_session(lockdownd_client_ + debug_info("Failed to get SessionID!"); + } + +- debug_info("Enable SSL Session: %s", (use_ssl?"true":"false")); ++ debug_info("Enable SSL Session: %s", (use_ssl ? "true" : "false")); + + if (use_ssl) { +- plret = property_list_service_enable_ssl(client->parent); +- if (plret == PROPERTY_LIST_SERVICE_E_SUCCESS) { +- ret = LOCKDOWN_E_SUCCESS; +- client->ssl_enabled = 1; +- } else { +- ret = LOCKDOWN_E_SSL_ERROR; +- client->ssl_enabled = 0; +- } ++ ret = lockdownd_error(property_list_service_enable_ssl(client->parent)); ++ client->ssl_enabled = (ret == LOCKDOWN_E_SUCCESS ? 1 : 0); + } else { +- client->ssl_enabled = 0; + ret = LOCKDOWN_E_SUCCESS; ++ client->ssl_enabled = 0; + } + } + +diff --git a/src/property_list_service.c b/src/property_list_service.c +index a5bdf9b..f411699 100644 +--- a/src/property_list_service.c ++++ b/src/property_list_service.c +@@ -98,7 +98,8 @@ LIBIMOBILEDEVICE_API property_list_service_error_t property_list_service_client_ + * @return PROPERTY_LIST_SERVICE_E_SUCCESS on success, + * PROPERTY_LIST_SERVICE_E_INVALID_ARG when one or more parameters are + * invalid, PROPERTY_LIST_SERVICE_E_PLIST_ERROR when dict is not a valid +- * plist, or PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR when an unspecified ++ * plist, PROPERTY_LIST_SERVICE_E_MUX_ERROR when a communication error ++ * occurs, or PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR when an unspecified + * error occurs. + */ + static property_list_service_error_t internal_plist_send(property_list_service_client_t client, plist_t plist, int binary) +@@ -140,6 +141,7 @@ static property_list_service_error_t internal_plist_send(property_list_service_c + } + if (bytes <= 0) { + debug_info("ERROR: sending to device failed."); ++ res = PROPERTY_LIST_SERVICE_E_MUX_ERROR; + } + + free(content); +-- +2.23.0 + + +From 4bdea2983a3204332b09408c62e440a0b8e23605 Mon Sep 17 00:00:00 2001 +From: BALATON Zoltan +Date: Tue, 7 Feb 2017 17:13:22 +0100 +Subject: [PATCH 054/151] Added IDEVICE_DEVICE_PAIRED event constant matching + the corresponding event number in libusbmuxd + +--- + include/libimobiledevice/libimobiledevice.h | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/include/libimobiledevice/libimobiledevice.h b/include/libimobiledevice/libimobiledevice.h +index b125adf..68eb511 100644 +--- a/include/libimobiledevice/libimobiledevice.h ++++ b/include/libimobiledevice/libimobiledevice.h +@@ -55,7 +55,8 @@ typedef idevice_connection_private *idevice_connection_t; /**< The connection ha + /** The event type for device add or removal */ + enum idevice_event_type { + IDEVICE_DEVICE_ADD = 1, +- IDEVICE_DEVICE_REMOVE ++ IDEVICE_DEVICE_REMOVE, ++ IDEVICE_DEVICE_PAIRED + }; + + /* event data structure */ +-- +2.23.0 + + +From f8999ef550fe9a97b24f4bbb17b66f186a5deae1 Mon Sep 17 00:00:00 2001 +From: BALATON Zoltan +Date: Tue, 7 Feb 2017 17:15:46 +0100 +Subject: [PATCH 055/151] Define htobe16 if not defined + +--- + include/endianness.h | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/include/endianness.h b/include/endianness.h +index 585e768..2d6ad0e 100644 +--- a/include/endianness.h ++++ b/include/endianness.h +@@ -27,6 +27,10 @@ + #endif + #endif + ++#ifndef htobe16 ++#define htobe16 be16toh ++#endif ++ + #ifndef __bswap_32 + #define __bswap_32(x) ((((x) & 0xFF000000) >> 24) \ + | (((x) & 0x00FF0000) >> 8) \ +-- +2.23.0 + + +From 1d844aae7820d10abf9a19b7acfb88341ac6e961 Mon Sep 17 00:00:00 2001 +From: BALATON Zoltan +Date: Tue, 7 Feb 2017 17:17:03 +0100 +Subject: [PATCH 056/151] Fix parameter check of + instproxy_check_capabilities_match() + +The capabilities parameter is a string array not a plist. Also check +other parameters when we are at it. +--- + src/installation_proxy.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/installation_proxy.c b/src/installation_proxy.c +index 9f367aa..f82eecc 100644 +--- a/src/installation_proxy.c ++++ b/src/installation_proxy.c +@@ -772,7 +772,7 @@ LIBIMOBILEDEVICE_API instproxy_error_t instproxy_remove_archive(instproxy_client + + LIBIMOBILEDEVICE_API instproxy_error_t instproxy_check_capabilities_match(instproxy_client_t client, const char** capabilities, plist_t client_options, plist_t *result) + { +- if (!capabilities || (plist_get_node_type(capabilities) != PLIST_ARRAY && plist_get_node_type(capabilities) != PLIST_DICT)) ++ if (!client || !capabilities || !result) + return INSTPROXY_E_INVALID_ARG; + + plist_t lookup_result = NULL; +-- +2.23.0 + + +From 02a0e03e24bc96bba2e5ea2438c30baf803fd137 Mon Sep 17 00:00:00 2001 +From: Christophe Fergeau +Date: Tue, 25 Apr 2017 14:09:48 +0200 +Subject: [PATCH 057/151] Avoid double free with OpenSSL 1.1.0 + +Since commit OpenSSL_1_1_0-pre3~178 +https://github.com/openssl/openssl/commit/b184e3ef73200cb3b7914a603b43a5b8a074c85f +OpenSSL automatically cleans up some of its internal data when the +program exits. This conflicts with some similar clean up +libimobiledevice attempts to do, which causes a double-free. +SSL_COMP_free_compression_methods() was available in OpenSSL 1.0.2, +and is still there in 1.1.0 as a no-op, so we can use that to free +the compression methods. + +This bug can be hit with a simple idevicebackup2 --help + +==14299== Invalid read of size 4 +==14299== at 0x547AEBC: OPENSSL_sk_pop_free (stack.c:263) +==14299== by 0x508B848: ssl_library_stop (ssl_init.c:182) +==14299== by 0x5424D11: OPENSSL_cleanup (init.c:402) +==14299== by 0x5DC3134: __cxa_finalize (cxa_finalize.c:56) +==14299== by 0x53332B2: ??? (in /usr/lib64/libcrypto.so.1.1.0e) +==14299== by 0x4011232: _dl_fini (dl-fini.c:235) +==14299== by 0x5DC2DC7: __run_exit_handlers (exit.c:83) +==14299== by 0x5DC2E19: exit (exit.c:105) +==14299== by 0x5DA8604: (below main) (libc-start.c:329) +==14299== Address 0x6585590 is 0 bytes inside a block of size 40 free'd +==14299== at 0x4C2FCC8: free (vg_replace_malloc.c:530) +==14299== by 0x4E43381: sk_SSL_COMP_free (ssl.h:830) +==14299== by 0x4E434E7: internal_idevice_deinit (idevice.c:103) +==14299== by 0x5B79643: __pthread_once_slow (pthread_once.c:116) +==14299== by 0x4E5663A: thread_once (thread.c:104) +==14299== by 0x4E43525: libimobiledevice_deinitialize (idevice.c:140) +==14299== by 0x4011232: _dl_fini (dl-fini.c:235) +==14299== by 0x5DC2DC7: __run_exit_handlers (exit.c:83) +==14299== by 0x5DC2E19: exit (exit.c:105) +==14299== by 0x5DA8604: (below main) (libc-start.c:329) +==14299== Block was alloc'd at +==14299== at 0x4C2EB1B: malloc (vg_replace_malloc.c:299) +==14299== by 0x5428908: CRYPTO_zalloc (mem.c:100) +==14299== by 0x547A9AE: OPENSSL_sk_new (stack.c:108) +==14299== by 0x5087D43: sk_SSL_COMP_new (ssl.h:830) +==14299== by 0x5087D43: do_load_builtin_compressions (ssl_ciph.c:482) +==14299== by 0x5087D43: do_load_builtin_compressions_ossl_ (ssl_ciph.c:476) +==14299== by 0x5B79643: __pthread_once_slow (pthread_once.c:116) +==14299== by 0x547B198: CRYPTO_THREAD_run_once (threads_pthread.c:106) +==14299== by 0x5089F96: load_builtin_compressions (ssl_ciph.c:500) +==14299== by 0x5089F96: SSL_COMP_get_compression_methods (ssl_ciph.c:1845) +==14299== by 0x508B68B: ossl_init_ssl_base (ssl_init.c:125) +==14299== by 0x508B68B: ossl_init_ssl_base_ossl_ (ssl_init.c:25) +==14299== by 0x5B79643: __pthread_once_slow (pthread_once.c:116) +==14299== by 0x547B198: CRYPTO_THREAD_run_once (threads_pthread.c:106) +==14299== by 0x508B90A: OPENSSL_init_ssl (ssl_init.c:227) +==14299== by 0x4E43416: internal_idevice_init (idevice.c:73) += + +Signed-off-by: Christophe Fergeau +--- + src/idevice.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/src/idevice.c b/src/idevice.c +index 913038e..d1f13cb 100644 +--- a/src/idevice.c ++++ b/src/idevice.c +@@ -51,6 +51,14 @@ + #include "common/debug.h" + + #ifdef HAVE_OPENSSL ++ ++#if OPENSSL_VERSION_NUMBER < 0x10002000L ++static void SSL_COMP_free_compression_methods(void) ++{ ++ sk_SSL_COMP_free(SSL_COMP_get_compression_methods()); ++} ++#endif ++ + static mutex_t *mutex_buf = NULL; + static void locking_function(int mode, int n, const char* file, int line) + { +@@ -100,7 +108,7 @@ static void internal_idevice_deinit(void) + + EVP_cleanup(); + CRYPTO_cleanup_all_ex_data(); +- sk_SSL_COMP_free(SSL_COMP_get_compression_methods()); ++ SSL_COMP_free_compression_methods(); + #ifdef HAVE_ERR_REMOVE_THREAD_STATE + ERR_remove_thread_state(NULL); + #else +-- +2.23.0 + + +From f635812ccc9b2eb63f5bc2b494d7fdae9c9e1ef3 Mon Sep 17 00:00:00 2001 +From: Christophe Fergeau +Date: Wed, 26 Apr 2017 11:36:54 +0200 +Subject: [PATCH 058/151] Don't use ERR_remove_thread_state() with OpenSSL + 1.1.0 + +It's deprecated and causes compile-time warnings. We don't want to +fallback to ERR_remove_state() either as it's similarly deprecated. + +This commit adds a helper functions to hide the #ifdef mess between +the various openssl versions. + +Signed-off-by: Christophe Fergeau +--- + src/idevice.c | 30 ++++++++++++++++-------------- + 1 file changed, 16 insertions(+), 14 deletions(-) + +diff --git a/src/idevice.c b/src/idevice.c +index d1f13cb..1c43269 100644 +--- a/src/idevice.c ++++ b/src/idevice.c +@@ -37,10 +37,7 @@ + #ifdef HAVE_OPENSSL + #include + #include +-#if OPENSSL_VERSION_NUMBER >= 0x10000001L +-/* since OpenSSL 1.0.0-beta1 */ +-#define HAVE_ERR_REMOVE_THREAD_STATE 1 +-#endif ++ + #else + #include + #endif +@@ -59,6 +56,19 @@ static void SSL_COMP_free_compression_methods(void) + } + #endif + ++static void openssl_remove_thread_state(void) ++{ ++/* ERR_remove_thread_state() is available since OpenSSL 1.0.0-beta1, but ++ * deprecated in OpenSSL 1.1.0 */ ++#if OPENSSL_VERSION_NUMBER < 0x10100000L ++#if OPENSSL_VERSION_NUMBER >= 0x10000001L ++ ERR_remove_thread_state(NULL); ++#else ++ ERR_remove_state(0); ++#endif ++#endif ++} ++ + static mutex_t *mutex_buf = NULL; + static void locking_function(int mode, int n, const char* file, int line) + { +@@ -109,11 +119,7 @@ static void internal_idevice_deinit(void) + EVP_cleanup(); + CRYPTO_cleanup_all_ex_data(); + SSL_COMP_free_compression_methods(); +-#ifdef HAVE_ERR_REMOVE_THREAD_STATE +- ERR_remove_thread_state(NULL); +-#else +- ERR_remove_state(0); +-#endif ++ openssl_remove_thread_state(); + #else + gnutls_global_deinit(); + #endif +@@ -764,11 +770,7 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_enable_ssl(idevice_conne + debug_info("SSL mode enabled, cipher: %s", SSL_get_cipher(ssl)); + } + /* required for proper multi-thread clean up to prevent leaks */ +-#ifdef HAVE_ERR_REMOVE_THREAD_STATE +- ERR_remove_thread_state(NULL); +-#else +- ERR_remove_state(0); +-#endif ++ openssl_remove_thread_state(); + #else + ssl_data_t ssl_data_loc = (ssl_data_t)malloc(sizeof(struct ssl_data_private)); + +-- +2.23.0 + + +From b89e4823ef9528936072f5f195d7fdab9e1f838b Mon Sep 17 00:00:00 2001 +From: Christophe Fergeau +Date: Tue, 25 Apr 2017 16:59:15 +0200 +Subject: [PATCH 059/151] #ifdef out code which is a no-op with OpenSSL 1.1.0 + +CRYPTO_set_id_callback +CRYPTO_set_locking_callback +EVP_cleanup +CRYPTO_cleanup_all_ex_data +SSL_COMP_free_compression_methods + +are all no-ops with OpenSSL 1.1.0, so we can #ifdef out the +corresponding code. This cleans up some warnings about +id_function/locking_function being defined but unused (as the calls to +CRYPTO_set_id_callback and CRYPTO_set_locking_callback disappear at +preprocessing time). + +Signed-off-by: Christophe Fergeau +--- + src/idevice.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/src/idevice.c b/src/idevice.c +index 1c43269..89724ff 100644 +--- a/src/idevice.c ++++ b/src/idevice.c +@@ -69,6 +69,7 @@ static void openssl_remove_thread_state(void) + #endif + } + ++#if OPENSSL_VERSION_NUMBER < 0x10100000L + static mutex_t *mutex_buf = NULL; + static void locking_function(int mode, int n, const char* file, int line) + { +@@ -83,10 +84,12 @@ static unsigned long id_function(void) + return ((unsigned long)THREAD_ID); + } + #endif ++#endif + + static void internal_idevice_init(void) + { + #ifdef HAVE_OPENSSL ++#if OPENSSL_VERSION_NUMBER < 0x10100000L + int i; + SSL_library_init(); + +@@ -98,6 +101,7 @@ static void internal_idevice_init(void) + + CRYPTO_set_id_callback(id_function); + CRYPTO_set_locking_callback(locking_function); ++#endif + #else + gnutls_global_init(); + #endif +@@ -106,6 +110,7 @@ static void internal_idevice_init(void) + static void internal_idevice_deinit(void) + { + #ifdef HAVE_OPENSSL ++#if OPENSSL_VERSION_NUMBER < 0x10100000L + int i; + if (mutex_buf) { + CRYPTO_set_id_callback(NULL); +@@ -120,6 +125,7 @@ static void internal_idevice_deinit(void) + CRYPTO_cleanup_all_ex_data(); + SSL_COMP_free_compression_methods(); + openssl_remove_thread_state(); ++#endif + #else + gnutls_global_deinit(); + #endif +-- +2.23.0 + + +From a5b2266b4e9c2112f85f94aa1d45440007922e08 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Thu, 27 Apr 2017 14:32:49 +0200 +Subject: [PATCH 060/151] cython: Fix build error after error constant rename + +--- + cython/lockdown.pxi | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/cython/lockdown.pxi b/cython/lockdown.pxi +index c8d511e..f249049 100644 +--- a/cython/lockdown.pxi ++++ b/cython/lockdown.pxi +@@ -7,7 +7,7 @@ cdef extern from "libimobiledevice/lockdown.h": + LOCKDOWN_E_PAIRING_FAILED + LOCKDOWN_E_SSL_ERROR + LOCKDOWN_E_DICT_ERROR +- LOCKDOWN_E_NOT_ENOUGH_DATA ++ LOCKDOWN_E_RECEIVE_TIMEOUT + LOCKDOWN_E_SET_VALUE_PROHIBITED + LOCKDOWN_E_GET_VALUE_PROHIBITED + LOCKDOWN_E_MUX_ERROR +@@ -78,7 +78,7 @@ cdef class LockdownError(BaseError): + LOCKDOWN_E_PAIRING_FAILED: "Pairing failed", + LOCKDOWN_E_SSL_ERROR: "SSL error", + LOCKDOWN_E_DICT_ERROR: "Dictionary error", +- LOCKDOWN_E_NOT_ENOUGH_DATA: "Not enough data", ++ LOCKDOWN_E_RECEIVE_TIMEOUT: "Receive timeout", + LOCKDOWN_E_MUX_ERROR: "Mux Protocol Error", + LOCKDOWN_E_NO_RUNNING_SESSION: "No running session", + LOCKDOWN_E_INVALID_RESPONSE: "Invalid response", +-- +2.23.0 + + +From 0cf6bb6f5bece0885c6e4806b5e62ec4296ab75e Mon Sep 17 00:00:00 2001 +From: Nikos Mavrogiannopoulos +Date: Mon, 2 Jan 2017 14:35:39 +0100 +Subject: [PATCH 061/151] gnutls: check for interrupted gnutls_handshake() + +That is, recover if gnutls_handshake() returns with non fatal +error codes like GNUTLS_E_INTERRUPTED or GNUTLS_E_AGAIN. +--- + src/idevice.c | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) + +diff --git a/src/idevice.c b/src/idevice.c +index 89724ff..21b10ba 100644 +--- a/src/idevice.c ++++ b/src/idevice.c +@@ -697,7 +697,11 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_enable_ssl(idevice_conne + return IDEVICE_E_INVALID_ARG; + + idevice_error_t ret = IDEVICE_E_SSL_ERROR; ++#ifdef HAVE_OPENSSL + uint32_t return_me = 0; ++#else ++ int return_me = 0; ++#endif + plist_t pair_record = NULL; + + userpref_read_pair_record(connection->udid, &pair_record); +@@ -817,14 +821,17 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_enable_ssl(idevice_conne + if (errno) { + debug_info("WARNING: errno says %s before handshake!", strerror(errno)); + } +- return_me = gnutls_handshake(ssl_data_loc->session); ++ ++ do { ++ return_me = gnutls_handshake(ssl_data_loc->session); ++ } while(return_me == GNUTLS_E_AGAIN || return_me == GNUTLS_E_INTERRUPTED); ++ + debug_info("GnuTLS handshake done..."); + + if (return_me != GNUTLS_E_SUCCESS) { + internal_ssl_cleanup(ssl_data_loc); + free(ssl_data_loc); +- debug_info("GnuTLS reported something wrong."); +- gnutls_perror(return_me); ++ debug_info("GnuTLS reported something wrong: %s", gnutls_strerror(return_me)); + debug_info("oh.. errno says %s", strerror(errno)); + } else { + connection->ssl_data = ssl_data_loc; +-- +2.23.0 + + +From 53fede06af98e24e26939127fcc71c6acfaf4c12 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Fri, 28 Apr 2017 20:58:53 +0200 +Subject: [PATCH 062/151] Updated README with some notes about configuration + options + +--- + README | 18 ++++++++++++++---- + 1 file changed, 14 insertions(+), 4 deletions(-) + +diff --git a/README b/README +index 972cfa8..efc09c0 100644 +--- a/README ++++ b/README +@@ -8,7 +8,7 @@ Requirements + ============ + + Development Packages of: +- libgnutls or openssl ++ OpenSSL or GnuTLS + libplist + libusbmuxd + +@@ -20,7 +20,7 @@ Software: + autoconf + libtool + pkg-config +- gcc ++ gcc or clang + + Optional: + cython (Python bindings) +@@ -34,6 +34,16 @@ To compile run: + make + sudo make install + ++If you require a custom prefix or other option being passed to ./configure ++you can pass them directly to ./autogen.sh like this: ++ ./autogen.sh --prefix=/opt/local --enable-debug-code ++ make ++ sudo make install ++ ++By default, OpenSSL will be used. If you prefer GnuTLS, configure with ++ --disable-openssl like this: ++ ./autogen.sh --disable-openssl ++ + Who/What/Where? + =============== + +@@ -47,7 +57,7 @@ Code (Mirror): + git clone https://github.com/libimobiledevice/libimobiledevice.git + + Tickets: +- http://github.com/libimobiledevice/libimobiledevice/issues ++ https://github.com/libimobiledevice/libimobiledevice/issues + + Mailing List: + http://lists.libimobiledevice.org/mailman/listinfo/libimobiledevice-devel +@@ -66,4 +76,4 @@ libimobiledevice is an independent software library and has not been + authorized, sponsored, or otherwise approved by Apple Inc. + + README Updated on: +- 2015-01-28 ++ 2017-04-28 +-- +2.23.0 + + +From 835d84b678d23f92622445f5bf142c2bf52a7e9b Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Sun, 18 Jun 2017 04:10:57 +0200 +Subject: [PATCH 063/151] idevicescreenshot: Detect screenshot image format to + determine file extension + +--- + tools/idevicescreenshot.c | 20 +++++++++++++++----- + 1 file changed, 15 insertions(+), 5 deletions(-) + +diff --git a/tools/idevicescreenshot.c b/tools/idevicescreenshot.c +index da229e2..74acdf6 100644 +--- a/tools/idevicescreenshot.c ++++ b/tools/idevicescreenshot.c +@@ -99,12 +99,22 @@ int main(int argc, char **argv) + } else { + char *imgdata = NULL; + uint64_t imgsize = 0; +- if (!filename) { +- time_t now = time(NULL); +- filename = (char*)malloc(36); +- strftime(filename, 36, "screenshot-%Y-%m-%d-%H-%M-%S.tiff", gmtime(&now)); +- } + if (screenshotr_take_screenshot(shotr, &imgdata, &imgsize) == SCREENSHOTR_E_SUCCESS) { ++ if (!filename) { ++ const char *fileext = NULL; ++ if (memcmp(imgdata, "\x89PNG", 4) == 0) { ++ fileext = ".png"; ++ } else if (memcmp(imgdata, "MM\x00*", 4) == 0) { ++ fileext = ".tiff"; ++ } else { ++ printf("WARNING: screenshot data has unexpected image format.\n"); ++ fileext = ".dat"; ++ } ++ time_t now = time(NULL); ++ filename = (char*)malloc(36); ++ size_t pos = strftime(filename, 36, "screenshot-%Y-%m-%d-%H-%M-%S", gmtime(&now)); ++ sprintf(filename+pos, "%s", fileext); ++ } + FILE *f = fopen(filename, "wb"); + if (f) { + if (fwrite(imgdata, 1, (size_t)imgsize, f) == (size_t)imgsize) { +-- +2.23.0 + + +From 5250024b53b799a427a486ae133ecb927f5c555e Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Sat, 2 Jul 2016 01:37:50 +0200 +Subject: [PATCH 064/151] Add basic mobileactivation service implementation + +--- + include/Makefile.am | 1 + + include/libimobiledevice/mobileactivation.h | 144 ++++++++++++++ + src/Makefile.am | 1 + + src/mobileactivation.c | 209 ++++++++++++++++++++ + src/mobileactivation.h | 32 +++ + 5 files changed, 387 insertions(+) + create mode 100644 include/libimobiledevice/mobileactivation.h + create mode 100644 src/mobileactivation.c + create mode 100644 src/mobileactivation.h + +diff --git a/include/Makefile.am b/include/Makefile.am +index 9f61e6b..f2b93ed 100644 +--- a/include/Makefile.am ++++ b/include/Makefile.am +@@ -20,5 +20,6 @@ nobase_include_HEADERS = libimobiledevice/libimobiledevice.h \ + libimobiledevice/diagnostics_relay.h\ + libimobiledevice/debugserver.h\ + libimobiledevice/syslog_relay.h\ ++ libimobiledevice/mobileactivation.h\ + libimobiledevice/property_list_service.h\ + libimobiledevice/service.h +diff --git a/include/libimobiledevice/mobileactivation.h b/include/libimobiledevice/mobileactivation.h +new file mode 100644 +index 0000000..bb977fe +--- /dev/null ++++ b/include/libimobiledevice/mobileactivation.h +@@ -0,0 +1,144 @@ ++/** ++ * @file libimobiledevice/mobileactivation.h ++ * @brief Handle device activation and deactivation. ++ * \internal ++ * ++ * Copyright (c) 2016 Nikias Bassen, All Rights Reserved. ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#ifndef IMOBILEACTIVATION_H ++#define IMOBILEACTIVATION_H ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#include ++#include ++ ++#define MOBILEACTIVATION_SERVICE_NAME "com.apple.mobileactivationd" ++ ++/** Error Codes */ ++typedef enum { ++ MOBILEACTIVATION_E_SUCCESS = 0, ++ MOBILEACTIVATION_E_INVALID_ARG = -1, ++ MOBILEACTIVATION_E_PLIST_ERROR = -2, ++ MOBILEACTIVATION_E_MUX_ERROR = -3, ++ MOBILEACTIVATION_E_UNKNOWN_REQUEST = -4, ++ MOBILEACTIVATION_E_REQUEST_FAILED = -5, ++ MOBILEACTIVATION_E_UNKNOWN_ERROR = -256 ++} mobileactivation_error_t; ++ ++typedef struct mobileactivation_client_private mobileactivation_client_private; ++typedef mobileactivation_client_private *mobileactivation_client_t; /**< The client handle. */ ++ ++/** ++ * Connects to the mobileactivation service on the specified device. ++ * ++ * @param device The device to connect to. ++ * @param service The service descriptor returned by lockdownd_start_service. ++ * @param client Reference that will point to a newly allocated ++ * mobileactivation_client_t upon successful return. ++ * ++ * @return MOBILEACTIVATION_E_SUCCESS on success, ++ * MOBILEACTIVATION_E_INVALID_ARG when one of the parameters is invalid, ++ * or MOBILEACTIVATION_E_MUX_ERROR when the connection failed. ++ */ ++mobileactivation_error_t mobileactivation_client_new(idevice_t device, lockdownd_service_descriptor_t service, mobileactivation_client_t *client); ++ ++/** ++ * Starts a new mobileactivation service on the specified device and connects to it. ++ * ++ * @param device The device to connect to. ++ * @param client Pointer that will point to a newly allocated ++ * mobileactivation_client_t upon successful return. Must be freed using ++ * mobileactivation_client_free() after use. ++ * @param label The label to use for communication. Usually the program name. ++ * Pass NULL to disable sending the label in requests to lockdownd. ++ * ++ * @return MOBILEACTIVATION_E_SUCCESS on success, or an MOBILEACTIVATION_E_* ++ * error code otherwise. ++ */ ++mobileactivation_error_t mobileactivation_client_start_service(idevice_t device, mobileactivation_client_t* client, const char* label); ++ ++/** ++ * Disconnects a mobileactivation client from the device and frees up the ++ * mobileactivation client data. ++ * ++ * @param client The mobileactivation client to disconnect and free. ++ * ++ * @return MOBILEACTIVATION_E_SUCCESS on success, ++ * MOBILEACTIVATION_E_INVALID_ARG when one of client or client->parent ++ * is invalid, or MOBILEACTIVATION_E_UNKNOWN_ERROR when the was an ++ * error freeing the parent property_list_service client. ++ */ ++mobileactivation_error_t mobileactivation_client_free(mobileactivation_client_t client); ++ ++ ++/** ++ * Retrieves the device's activation state. ++ * ++ * @param client The mobileactivation client. ++ * @param state Pointer to a plist_t variable that will be set to the ++ * activation state reported by the mobileactivation service. The ++ * consumer is responsible for freeing the returned object using ++ * plist_free(). ++ * ++ * @return MOBILEACTIVATION_E_SUCCESS on success, or an MOBILEACTIVATION_E_* ++ * error code otherwise. ++ */ ++mobileactivation_error_t mobileactivation_get_activation_state(mobileactivation_client_t client, plist_t *state); ++ ++/** ++ * Retrieves the activation info required for device activation. ++ * ++ * @param client The mobileactivation client ++ * @param info Pointer to a plist_t variable that will be set to the ++ * activation info created by the mobileactivation service. The ++ * consumer is responsible for freeing the returned object using ++ * plist_free(). ++ * ++ * @return MOBILEACTIVATION_E_SUCCESS on success, or an MOBILEACTIVATION_E_* ++ * error code otherwise. ++ */ ++mobileactivation_error_t mobileactivation_create_activation_info(mobileactivation_client_t client, plist_t *info); ++ ++/** ++ * Activates the device with the given activation record. ++ * The activation record plist dictionary must be obtained using the ++ * activation protocol requesting from Apple's https webservice. ++ * ++ * @param client The mobileactivation client ++ * @param activation_record The activation record plist dictionary ++ * ++ * @return MOBILEACTIVATION_E_SUCCESS on success, or an MOBILEACTIVATION_E_* ++ * error code otherwise. ++ */ ++mobileactivation_error_t mobileactivation_activate(mobileactivation_client_t client, plist_t activation_record); ++ ++/** ++ * Deactivates the device. ++ * ++ * @param client The mobileactivation client ++ */ ++mobileactivation_error_t mobileactivation_deactivate(mobileactivation_client_t client); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +diff --git a/src/Makefile.am b/src/Makefile.am +index efd95eb..fcde8ae 100644 +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -28,6 +28,7 @@ libimobiledevice_la_SOURCES = idevice.c idevice.h \ + heartbeat.c heartbeat.h\ + debugserver.c debugserver.h\ + webinspector.c webinspector.h\ ++ mobileactivation.c mobileactivation.h\ + syslog_relay.c syslog_relay.h + + if WIN32 +diff --git a/src/mobileactivation.c b/src/mobileactivation.c +new file mode 100644 +index 0000000..f14eb73 +--- /dev/null ++++ b/src/mobileactivation.c +@@ -0,0 +1,209 @@ ++/* ++ * mobileactivation.c ++ * com.apple.mobileactivationd service implementation. ++ * ++ * Copyright (c) 2016 Nikias Bassen, All Rights Reserved. ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++#include ++#include ++#include "mobileactivation.h" ++#include "property_list_service.h" ++#include "common/debug.h" ++ ++/** ++ * Convert a property_list_service_error_t value to a mobileactivation_error_t value. ++ * Used internally to get correct error codes. ++ * ++ * @param err An property_list_service_error_t error code ++ * ++ * @return A matching mobileactivation_error_t error code, ++ * MOBILEACTIVATION_E_UNKNOWN_ERROR otherwise. ++ */ ++static mobileactivation_error_t mobileactivation_error(property_list_service_error_t err) ++{ ++ switch (err) { ++ case PROPERTY_LIST_SERVICE_E_SUCCESS: ++ return MOBILEACTIVATION_E_SUCCESS; ++ case PROPERTY_LIST_SERVICE_E_INVALID_ARG: ++ return MOBILEACTIVATION_E_INVALID_ARG; ++ case PROPERTY_LIST_SERVICE_E_PLIST_ERROR: ++ return MOBILEACTIVATION_E_PLIST_ERROR; ++ case PROPERTY_LIST_SERVICE_E_MUX_ERROR: ++ return MOBILEACTIVATION_E_MUX_ERROR; ++ default: ++ break; ++ } ++ return MOBILEACTIVATION_E_UNKNOWN_ERROR; ++} ++ ++LIBIMOBILEDEVICE_API mobileactivation_error_t mobileactivation_client_new(idevice_t device, lockdownd_service_descriptor_t service, mobileactivation_client_t *client) ++{ ++ if (!device || !service || service->port == 0 || !client || *client) { ++ return MOBILEACTIVATION_E_INVALID_ARG; ++ } ++ ++ property_list_service_client_t plistclient = NULL; ++ if (property_list_service_client_new(device, service, &plistclient) != PROPERTY_LIST_SERVICE_E_SUCCESS) { ++ return MOBILEACTIVATION_E_MUX_ERROR; ++ } ++ ++ /* create client object */ ++ mobileactivation_client_t client_loc = (mobileactivation_client_t) malloc(sizeof(struct mobileactivation_client_private)); ++ client_loc->parent = plistclient; ++ ++ /* all done, return success */ ++ *client = client_loc; ++ return MOBILEACTIVATION_E_SUCCESS; ++} ++ ++LIBIMOBILEDEVICE_API mobileactivation_error_t mobileactivation_client_start_service(idevice_t device, mobileactivation_client_t * client, const char* label) ++{ ++ mobileactivation_error_t err = MOBILEACTIVATION_E_UNKNOWN_ERROR; ++ service_client_factory_start_service(device, MOBILEACTIVATION_SERVICE_NAME, (void**)client, label, SERVICE_CONSTRUCTOR(mobileactivation_client_new), &err); ++ return err; ++} ++ ++LIBIMOBILEDEVICE_API mobileactivation_error_t mobileactivation_client_free(mobileactivation_client_t client) ++{ ++ if (!client) ++ return MOBILEACTIVATION_E_INVALID_ARG; ++ ++ if (property_list_service_client_free(client->parent) != PROPERTY_LIST_SERVICE_E_SUCCESS) { ++ return MOBILEACTIVATION_E_UNKNOWN_ERROR; ++ } ++ free(client); ++ return MOBILEACTIVATION_E_SUCCESS; ++} ++ ++static mobileactivation_error_t mobileactivation_check_result(plist_t dict, const char *command) ++{ ++ mobileactivation_error_t ret = MOBILEACTIVATION_E_UNKNOWN_ERROR; ++ ++ if (!dict || plist_get_node_type(dict) != PLIST_DICT) { ++ return MOBILEACTIVATION_E_PLIST_ERROR; ++ } ++ ++ plist_t err_node = plist_dict_get_item(dict, "Error"); ++ if (!err_node) { ++ return MOBILEACTIVATION_E_SUCCESS; ++ } else { ++ char *errmsg = NULL; ++ plist_get_string_val(err_node, &errmsg); ++ debug_info("ERROR: %s: %s", command, errmsg); ++ free(errmsg); ++ ret = MOBILEACTIVATION_E_REQUEST_FAILED; ++ } ++ return ret; ++} ++ ++static mobileactivation_error_t mobileactivation_send_command(mobileactivation_client_t client, const char* command, plist_t value, plist_t *result) ++{ ++ if (!client || !command || !result) ++ return MOBILEACTIVATION_E_INVALID_ARG; ++ ++ mobileactivation_error_t ret = MOBILEACTIVATION_E_UNKNOWN_ERROR; ++ *result = NULL; ++ ++ plist_t dict = plist_new_dict(); ++ plist_dict_set_item(dict, "Command", plist_new_string(command)); ++ if (value) { ++ plist_dict_set_item(dict, "Value", plist_copy(value)); ++ } ++ ++ ret = mobileactivation_error(property_list_service_send_binary_plist(client->parent, dict)); ++ plist_free(dict); ++ dict = NULL; ++ ++ ret = mobileactivation_error(property_list_service_receive_plist(client->parent, &dict)); ++ if (!dict) { ++ debug_info("ERROR: Did not get reply for %s command", command); ++ return MOBILEACTIVATION_E_PLIST_ERROR; ++ } ++ ++ *result = dict; ++ return mobileactivation_check_result(dict, command); ++} ++ ++LIBIMOBILEDEVICE_API mobileactivation_error_t mobileactivation_get_activation_state(mobileactivation_client_t client, plist_t *state) ++{ ++ if (!client || !state) ++ return MOBILEACTIVATION_E_INVALID_ARG; ++ ++ plist_t result = NULL; ++ mobileactivation_error_t ret = mobileactivation_send_command(client, "GetActivationStateRequest", NULL, &result); ++ if (ret == MOBILEACTIVATION_E_SUCCESS) { ++ plist_t node = plist_dict_get_item(result, "Value"); ++ if (!node) { ++ debug_info("ERROR: GetActivationStateRequest command returned success but has no value in reply"); ++ ret = MOBILEACTIVATION_E_UNKNOWN_ERROR; ++ } else { ++ *state = plist_copy(node); ++ } ++ } ++ plist_free(result); ++ result = NULL; ++ ++ return ret; ++} ++ ++LIBIMOBILEDEVICE_API mobileactivation_error_t mobileactivation_create_activation_info(mobileactivation_client_t client, plist_t *info) ++{ ++ if (!client || !info) ++ return MOBILEACTIVATION_E_INVALID_ARG; ++ ++ plist_t result = NULL; ++ mobileactivation_error_t ret = mobileactivation_send_command(client, "CreateActivationInfoRequest", NULL, &result); ++ if (ret == MOBILEACTIVATION_E_SUCCESS) { ++ plist_t node = plist_dict_get_item(result, "Value"); ++ if (!node) { ++ debug_info("ERROR: CreateActivationInfoRequest command returned success but has no value in reply"); ++ ret = MOBILEACTIVATION_E_UNKNOWN_ERROR; ++ } else { ++ *info = plist_copy(node); ++ } ++ } ++ plist_free(result); ++ result = NULL; ++ ++ return ret; ++} ++ ++LIBIMOBILEDEVICE_API mobileactivation_error_t mobileactivation_activate(mobileactivation_client_t client, plist_t activation_record) ++{ ++ if (!client || !activation_record) ++ return MOBILEACTIVATION_E_INVALID_ARG; ++ ++ plist_t result = NULL; ++ mobileactivation_error_t ret = mobileactivation_send_command(client, "HandleActivationInfoRequest", activation_record, &result); ++ plist_free(result); ++ result = NULL; ++ ++ return ret; ++} ++ ++LIBIMOBILEDEVICE_API mobileactivation_error_t mobileactivation_deactivate(mobileactivation_client_t client) ++{ ++ if (!client) ++ return MOBILEACTIVATION_E_INVALID_ARG; ++ ++ plist_t result = NULL; ++ mobileactivation_error_t ret = mobileactivation_send_command(client, "DeactivateRequest", NULL, &result); ++ plist_free(result); ++ result = NULL; ++ ++ return ret; ++} +diff --git a/src/mobileactivation.h b/src/mobileactivation.h +new file mode 100644 +index 0000000..49b9ebc +--- /dev/null ++++ b/src/mobileactivation.h +@@ -0,0 +1,32 @@ ++/* ++ * mobileactivation.h ++ * com.apple.mobileactivationd service header file. ++ * ++ * Copyright (c) 2016 Nikias Bassen, All Rights Reserved. ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#ifndef __MOBILEACTIVATION_H ++#define __MOBILEACTIVATION_H ++ ++#include "libimobiledevice/mobileactivation.h" ++#include "property_list_service.h" ++ ++struct mobileactivation_client_private { ++ property_list_service_client_t parent; ++}; ++ ++#endif +-- +2.23.0 + + +From 0dbe76b4e75eef5d0e033aac99409fb6df36c512 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Mon, 3 Jul 2017 03:09:35 +0200 +Subject: [PATCH 065/151] mobileactivation: Add new functions required for + drmHandshake / session mode device activation + +--- + include/libimobiledevice/mobileactivation.h | 47 ++++++++++++- + src/mobileactivation.c | 75 ++++++++++++++++++++- + 2 files changed, 119 insertions(+), 3 deletions(-) + +diff --git a/include/libimobiledevice/mobileactivation.h b/include/libimobiledevice/mobileactivation.h +index bb977fe..bb1f3f4 100644 +--- a/include/libimobiledevice/mobileactivation.h ++++ b/include/libimobiledevice/mobileactivation.h +@@ -3,7 +3,7 @@ + * @brief Handle device activation and deactivation. + * \internal + * +- * Copyright (c) 2016 Nikias Bassen, All Rights Reserved. ++ * Copyright (c) 2016-2017 Nikias Bassen, All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public +@@ -103,6 +103,20 @@ mobileactivation_error_t mobileactivation_client_free(mobileactivation_client_t + */ + mobileactivation_error_t mobileactivation_get_activation_state(mobileactivation_client_t client, plist_t *state); + ++/** ++ * Retrieves a session blob required for 'drmHandshake' via albert.apple.com. ++ * ++ * @param client The mobileactivation client ++ * @param blob Pointer to a plist_t variable that will be set to the ++ * session blob created by the mobielactivation service. The ++ * consumer is responsible for freeing the returned object using ++ * plist_free(). ++ * ++ * @return MOBILEACTIVATION_E_SUCCESS on success, or an MOBILEACTIVATION_E_* ++ * error code otherwise. ++ */ ++mobileactivation_error_t mobileactivation_create_activation_session_info(mobileactivation_client_t client, plist_t *blob); ++ + /** + * Retrieves the activation info required for device activation. + * +@@ -117,6 +131,24 @@ mobileactivation_error_t mobileactivation_get_activation_state(mobileactivation_ + */ + mobileactivation_error_t mobileactivation_create_activation_info(mobileactivation_client_t client, plist_t *info); + ++/** ++ * Retrieves the activation info required for device activation in 'session' ++ * mode. This function expects a handshake result retrieved from ++ * https://albert.apple.com/deviceservies/drmHandshake with a blob ++ * provided by mobileactivation_create_activation_session_info(). ++ * ++ * @param client The mobileactivation client ++ * @aram handshake_result The handshake result returned from drmHandshake ++ * @param info Pointer to a plist_t variable that will be set to the ++ * activation info created by the mobileactivation service. The ++ * consumer is responsible for freeing the returned object using ++ * plist_free(). ++ * ++ * @return MOBILEACTIVATION_E_SUCCESS on success, or an MOBILEACTIVATION_E_* ++ * error code otherwise. ++ */ ++mobileactivation_error_t mobileactivation_create_activation_info_with_session(mobileactivation_client_t client, plist_t handshake_result, plist_t *info); ++ + /** + * Activates the device with the given activation record. + * The activation record plist dictionary must be obtained using the +@@ -130,6 +162,19 @@ mobileactivation_error_t mobileactivation_create_activation_info(mobileactivatio + */ + mobileactivation_error_t mobileactivation_activate(mobileactivation_client_t client, plist_t activation_record); + ++/** ++ * Activates the device with the given activation record in 'session' mode. ++ * The activation record plist dictionary must be obtained using the ++ * activation protocol requesting from Apple's https webservice. ++ * ++ * @param client The mobileactivation client ++ * @param activation_record The activation record plist dictionary ++ * ++ * @return MOBILEACTIVATION_E_SUCCESS on success, or an MOBILEACTIVATION_E_* ++ * error code otherwise. ++ */ ++mobileactivation_error_t mobileactivation_activate_with_session(mobileactivation_client_t client, plist_t activation_record); ++ + /** + * Deactivates the device. + * +diff --git a/src/mobileactivation.c b/src/mobileactivation.c +index f14eb73..7ae35bb 100644 +--- a/src/mobileactivation.c ++++ b/src/mobileactivation.c +@@ -2,7 +2,7 @@ + * mobileactivation.c + * com.apple.mobileactivationd service implementation. + * +- * Copyright (c) 2016 Nikias Bassen, All Rights Reserved. ++ * Copyright (c) 2016-2017 Nikias Bassen, All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public +@@ -89,6 +89,17 @@ LIBIMOBILEDEVICE_API mobileactivation_error_t mobileactivation_client_free(mobil + return MOBILEACTIVATION_E_SUCCESS; + } + ++static plist_t plist_data_from_plist(plist_t plist) ++{ ++ plist_t result = NULL; ++ char *xml = NULL; ++ uint32_t xml_len = 0; ++ plist_to_xml(plist, &xml, &xml_len); ++ result = plist_new_data(xml, xml_len); ++ free(xml); ++ return result; ++} ++ + static mobileactivation_error_t mobileactivation_check_result(plist_t dict, const char *command) + { + mobileactivation_error_t ret = MOBILEACTIVATION_E_UNKNOWN_ERROR; +@@ -104,8 +115,8 @@ static mobileactivation_error_t mobileactivation_check_result(plist_t dict, cons + char *errmsg = NULL; + plist_get_string_val(err_node, &errmsg); + debug_info("ERROR: %s: %s", command, errmsg); +- free(errmsg); + ret = MOBILEACTIVATION_E_REQUEST_FAILED; ++ free(errmsg); + } + return ret; + } +@@ -160,6 +171,26 @@ LIBIMOBILEDEVICE_API mobileactivation_error_t mobileactivation_get_activation_st + return ret; + } + ++LIBIMOBILEDEVICE_API mobileactivation_error_t mobileactivation_create_activation_session_info(mobileactivation_client_t client, plist_t *blob) ++{ ++ if (!client || !blob) ++ return MOBILEACTIVATION_E_INVALID_ARG; ++ ++ plist_t result = NULL; ++ mobileactivation_error_t ret = mobileactivation_send_command(client, "CreateTunnel1SessionInfoRequest", NULL, &result); ++ if (ret == MOBILEACTIVATION_E_SUCCESS) { ++ plist_t node = plist_dict_get_item(result, "Value"); ++ if (!node) { ++ debug_info("ERROR: CreateTunnel1SessionInfoRequest command returned success but has no value in reply"); ++ ret = MOBILEACTIVATION_E_UNKNOWN_ERROR; ++ } else { ++ *blob = plist_copy(node); ++ } ++ } ++ ++ return ret; ++} ++ + LIBIMOBILEDEVICE_API mobileactivation_error_t mobileactivation_create_activation_info(mobileactivation_client_t client, plist_t *info) + { + if (!client || !info) +@@ -179,6 +210,30 @@ LIBIMOBILEDEVICE_API mobileactivation_error_t mobileactivation_create_activation + plist_free(result); + result = NULL; + ++ return ret; ++} ++ ++LIBIMOBILEDEVICE_API mobileactivation_error_t mobileactivation_create_activation_info_with_session(mobileactivation_client_t client, plist_t handshake_response, plist_t *info) ++{ ++ if (!client || !info) ++ return MOBILEACTIVATION_E_INVALID_ARG; ++ ++ plist_t result = NULL; ++ plist_t data = plist_data_from_plist(handshake_response); ++ mobileactivation_error_t ret = mobileactivation_send_command(client, "CreateTunnel1ActivationInfoRequest", data, &result); ++ plist_free(data); ++ if (ret == MOBILEACTIVATION_E_SUCCESS) { ++ plist_t node = plist_dict_get_item(result, "Value"); ++ if (!node) { ++ debug_info("ERROR: CreateTunnel1ActivationInfoRequest command returned success but has no value in reply"); ++ ret = MOBILEACTIVATION_E_UNKNOWN_ERROR; ++ } else { ++ *info = plist_copy(node); ++ } ++ } ++ plist_free(result); ++ result = NULL; ++ + return ret; + } + +@@ -195,6 +250,22 @@ LIBIMOBILEDEVICE_API mobileactivation_error_t mobileactivation_activate(mobileac + return ret; + } + ++LIBIMOBILEDEVICE_API mobileactivation_error_t mobileactivation_activate_with_session(mobileactivation_client_t client, plist_t activation_record) ++{ ++ if (!client || !activation_record) ++ return MOBILEACTIVATION_E_INVALID_ARG; ++ ++ plist_t result = NULL; ++ plist_t data = plist_data_from_plist(activation_record); ++ mobileactivation_error_t ret = mobileactivation_send_command(client, "HandleActivationInfoWithSessionRequest", data, &result); ++ plist_free(data); ++ plist_free(result); ++ result = NULL; ++ ++ return ret; ++} ++ ++ + LIBIMOBILEDEVICE_API mobileactivation_error_t mobileactivation_deactivate(mobileactivation_client_t client) + { + if (!client) +-- +2.23.0 + + +From 5a85432719fb3d18027d528f87d2a44b76fd3e12 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Sun, 13 Aug 2017 00:12:16 +0200 +Subject: [PATCH 066/151] lockdown: Don't explicitly validate pairing unless + we're dealing with an older device + +On newer iOS version, ValidatePair is not mandatory to gain trusted host +status. Starting with iOS 11, the ValidatePair request has been removed from +lockdownd and will throw an error. This commit adds a version check so that +ValidatePair is only called on devices prior iOS 7. +--- + src/idevice.c | 1 + + src/idevice.h | 1 + + src/lockdown.c | 37 +++++++++++++++++++++++++------------ + 3 files changed, 27 insertions(+), 12 deletions(-) + +diff --git a/src/idevice.c b/src/idevice.c +index 21b10ba..ead9b86 100644 +--- a/src/idevice.c ++++ b/src/idevice.c +@@ -256,6 +256,7 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_new(idevice_t * device, const char + dev->udid = strdup(muxdev.udid); + dev->conn_type = CONNECTION_USBMUXD; + dev->conn_data = (void*)(long)muxdev.handle; ++ dev->version = 0; + *device = dev; + return IDEVICE_E_SUCCESS; + } +diff --git a/src/idevice.h b/src/idevice.h +index 1354cc0..e46a7e5 100644 +--- a/src/idevice.h ++++ b/src/idevice.h +@@ -76,6 +76,7 @@ struct idevice_private { + char *udid; + enum connection_type conn_type; + void *conn_data; ++ int version; + }; + + #endif +diff --git a/src/lockdown.c b/src/lockdown.c +index 5251737..071697d 100644 +--- a/src/lockdown.c ++++ b/src/lockdown.c +@@ -707,6 +707,19 @@ LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_client_new_with_handshake(idevi + } + free(type); + ++ if (device->version == 0) { ++ plist_t p_version = NULL; ++ if (lockdownd_get_value(client_loc, NULL, "ProductVersion", &p_version) == LOCKDOWN_E_SUCCESS) { ++ int vers[3] = {0, 0, 0}; ++ char *s_version = NULL; ++ plist_get_string_val(p_version, &s_version); ++ if (s_version && sscanf(s_version, "%d.%d.%d", &vers[0], &vers[1], &vers[2]) >= 2) { ++ device->version = ((vers[0] & 0xFF) << 16) | ((vers[1] & 0xFF) << 8) | (vers[2] & 0xFF); ++ } ++ free(s_version); ++ } ++ } ++ + userpref_read_pair_record(client_loc->udid, &pair_record); + if (pair_record) { + pair_record_get_host_id(pair_record, &host_id); +@@ -723,18 +736,18 @@ LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_client_new_with_handshake(idevi + plist_free(pair_record); + pair_record = NULL; + +- /* in any case, we need to validate pairing to receive trusted host status */ +- ret = lockdownd_validate_pair(client_loc, NULL); +- +- /* if not paired yet, let's do it now */ +- if (LOCKDOWN_E_INVALID_HOST_ID == ret) { +- free(host_id); +- host_id = NULL; +- ret = lockdownd_pair(client_loc, NULL); +- if (LOCKDOWN_E_SUCCESS == ret) { +- ret = lockdownd_validate_pair(client_loc, NULL); +- } else if (LOCKDOWN_E_PAIRING_DIALOG_RESPONSE_PENDING == ret) { +- debug_info("Device shows the pairing dialog."); ++ if (device->version < 0x070000) { ++ /* for older devices, we need to validate pairing to receive trusted host status */ ++ ret = lockdownd_validate_pair(client_loc, NULL); ++ ++ /* if not paired yet, let's do it now */ ++ if (LOCKDOWN_E_INVALID_HOST_ID == ret) { ++ free(host_id); ++ host_id = NULL; ++ ret = lockdownd_pair(client_loc, NULL); ++ if (LOCKDOWN_E_SUCCESS == ret) { ++ ret = lockdownd_validate_pair(client_loc, NULL); ++ } + } + } + +-- +2.23.0 + + +From 5b3fcb7fa704bcbf1a1cc655264ec0d6ab121799 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Thu, 7 Dec 2017 16:41:29 +0700 +Subject: [PATCH 067/151] mobileactivation: Don't convert activation record if + it is already passed as PLIST_DATA + +--- + src/mobileactivation.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/src/mobileactivation.c b/src/mobileactivation.c +index 7ae35bb..433497a 100644 +--- a/src/mobileactivation.c ++++ b/src/mobileactivation.c +@@ -91,6 +91,9 @@ LIBIMOBILEDEVICE_API mobileactivation_error_t mobileactivation_client_free(mobil + + static plist_t plist_data_from_plist(plist_t plist) + { ++ if (plist && plist_get_node_type(plist) == PLIST_DATA) { ++ return plist_copy(plist); ++ } + plist_t result = NULL; + char *xml = NULL; + uint32_t xml_len = 0; +-- +2.23.0 + + +From b7feed9f5a62833c1df3f503fd3693e2ed2e4738 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Thu, 7 Dec 2017 16:48:36 +0700 +Subject: [PATCH 068/151] mobileactivation: Allow passing activation response + headers as required for iOS 11.2+ + +When activating in session mode - which is required for newer iOS versions - +we can now pass the activation response headers with the activation command. +For iOS 11.2+ this is mandatory or the activation will fail. +--- + include/libimobiledevice/mobileactivation.h | 8 +-- + src/mobileactivation.c | 60 +++++++++++++++------ + 2 files changed, 50 insertions(+), 18 deletions(-) + +diff --git a/include/libimobiledevice/mobileactivation.h b/include/libimobiledevice/mobileactivation.h +index bb1f3f4..b7f8064 100644 +--- a/include/libimobiledevice/mobileactivation.h ++++ b/include/libimobiledevice/mobileactivation.h +@@ -164,16 +164,18 @@ mobileactivation_error_t mobileactivation_activate(mobileactivation_client_t cli + + /** + * Activates the device with the given activation record in 'session' mode. +- * The activation record plist dictionary must be obtained using the ++ * The activation record plist must be obtained using the + * activation protocol requesting from Apple's https webservice. + * + * @param client The mobileactivation client +- * @param activation_record The activation record plist dictionary ++ * @param activation_record The activation record in plist format ++ * @param headers A plist dictionary with the activation response headers ++ * as returned from Apple's https webservice with the activation record + * + * @return MOBILEACTIVATION_E_SUCCESS on success, or an MOBILEACTIVATION_E_* + * error code otherwise. + */ +-mobileactivation_error_t mobileactivation_activate_with_session(mobileactivation_client_t client, plist_t activation_record); ++mobileactivation_error_t mobileactivation_activate_with_session(mobileactivation_client_t client, plist_t activation_record, plist_t headers); + + /** + * Deactivates the device. +diff --git a/src/mobileactivation.c b/src/mobileactivation.c +index 433497a..010484e 100644 +--- a/src/mobileactivation.c ++++ b/src/mobileactivation.c +@@ -124,6 +124,38 @@ static mobileactivation_error_t mobileactivation_check_result(plist_t dict, cons + return ret; + } + ++static mobileactivation_error_t mobileactivation_send_command_plist(mobileactivation_client_t client, plist_t command, plist_t *result) ++{ ++ if (!client || !command) ++ return MOBILEACTIVATION_E_INVALID_ARG; ++ ++ plist_t cmd = plist_dict_get_item(command, "Command"); ++ char* command_str = NULL; ++ if (cmd) { ++ plist_get_string_val(cmd, &command_str); ++ } ++ if (!command_str) ++ return MOBILEACTIVATION_E_INVALID_ARG; ++ ++ mobileactivation_error_t ret = MOBILEACTIVATION_E_UNKNOWN_ERROR; ++ *result = NULL; ++ ++ ret = mobileactivation_error(property_list_service_send_binary_plist(client->parent, command)); ++ ++ plist_t dict = NULL; ++ ret = mobileactivation_error(property_list_service_receive_plist(client->parent, &dict)); ++ if (!dict) { ++ debug_info("ERROR: Did not get reply for %s command", command_str); ++ free(command_str); ++ return MOBILEACTIVATION_E_PLIST_ERROR; ++ } ++ ++ *result = dict; ++ ret = mobileactivation_check_result(dict, command_str); ++ free(command_str); ++ return ret; ++} ++ + static mobileactivation_error_t mobileactivation_send_command(mobileactivation_client_t client, const char* command, plist_t value, plist_t *result) + { + if (!client || !command || !result) +@@ -138,18 +170,9 @@ static mobileactivation_error_t mobileactivation_send_command(mobileactivation_c + plist_dict_set_item(dict, "Value", plist_copy(value)); + } + +- ret = mobileactivation_error(property_list_service_send_binary_plist(client->parent, dict)); ++ ret = mobileactivation_send_command_plist(client, dict, result); + plist_free(dict); +- dict = NULL; +- +- ret = mobileactivation_error(property_list_service_receive_plist(client->parent, &dict)); +- if (!dict) { +- debug_info("ERROR: Did not get reply for %s command", command); +- return MOBILEACTIVATION_E_PLIST_ERROR; +- } +- +- *result = dict; +- return mobileactivation_check_result(dict, command); ++ return ret; + } + + LIBIMOBILEDEVICE_API mobileactivation_error_t mobileactivation_get_activation_state(mobileactivation_client_t client, plist_t *state) +@@ -253,15 +276,22 @@ LIBIMOBILEDEVICE_API mobileactivation_error_t mobileactivation_activate(mobileac + return ret; + } + +-LIBIMOBILEDEVICE_API mobileactivation_error_t mobileactivation_activate_with_session(mobileactivation_client_t client, plist_t activation_record) ++LIBIMOBILEDEVICE_API mobileactivation_error_t mobileactivation_activate_with_session(mobileactivation_client_t client, plist_t activation_record, plist_t headers) + { + if (!client || !activation_record) + return MOBILEACTIVATION_E_INVALID_ARG; + + plist_t result = NULL; +- plist_t data = plist_data_from_plist(activation_record); +- mobileactivation_error_t ret = mobileactivation_send_command(client, "HandleActivationInfoWithSessionRequest", data, &result); +- plist_free(data); ++ ++ plist_t dict = plist_new_dict(); ++ plist_dict_set_item(dict, "Command", plist_new_string("HandleActivationInfoWithSessionRequest")); ++ plist_dict_set_item(dict, "Value", plist_data_from_plist(activation_record)); ++ if (headers) { ++ plist_dict_set_item(dict, "ActivationResponseHeaders", plist_copy(headers)); ++ } ++ ++ mobileactivation_error_t ret = mobileactivation_send_command_plist(client, dict, &result); ++ plist_free(dict); + plist_free(result); + result = NULL; + +-- +2.23.0 + + +From 344729536e49d6a98aa05d76a3637856748911cd Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Fri, 8 Dec 2017 00:42:38 +0700 +Subject: [PATCH 069/151] lockdown: Plug small memory leak + +Credit to Rudolf Tammekivi (Blefish), see issue #599 +--- + src/lockdown.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/lockdown.c b/src/lockdown.c +index 071697d..9d6d17d 100644 +--- a/src/lockdown.c ++++ b/src/lockdown.c +@@ -718,6 +718,7 @@ LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_client_new_with_handshake(idevi + } + free(s_version); + } ++ plist_free(p_version); + } + + userpref_read_pair_record(client_loc->udid, &pair_record); +-- +2.23.0 + + +From 3a37a4e4a334ea2de52db534f105fe8dbe928628 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Wed, 17 Jan 2018 13:10:05 +0200 +Subject: [PATCH 070/151] idevicesyslog: Wait for passcode entry on device when + required + +After device bootup several services cannot be used until the passcode +is entered on the device. This commit will detect this state and wait for +the passcode to be entered. Before this change you would have to restart +idevicesyslog or replug the device after entering the passcode to make +the logging work again. +--- + tools/idevicesyslog.c | 35 +++++++++++++++++++++++++++++++++-- + 1 file changed, 33 insertions(+), 2 deletions(-) + +diff --git a/tools/idevicesyslog.c b/tools/idevicesyslog.c +index 47d2f8c..0a923b8 100644 +--- a/tools/idevicesyslog.c ++++ b/tools/idevicesyslog.c +@@ -63,9 +63,40 @@ static int start_logging(void) + return -1; + } + +- /* start and connect to syslog_relay service */ ++ lockdownd_client_t lockdown = NULL; ++ lockdownd_error_t lerr = lockdownd_client_new_with_handshake(device, &lockdown, "idevicesyslog"); ++ if (lerr != LOCKDOWN_E_SUCCESS) { ++ fprintf(stderr, "ERROR: Could not connect to lockdownd: %d\n", lerr); ++ idevice_free(device); ++ device = NULL; ++ return -1; ++ } ++ ++ /* start syslog_relay service */ ++ lockdownd_service_descriptor_t svc = NULL; ++ lerr = lockdownd_start_service(lockdown, SYSLOG_RELAY_SERVICE_NAME, &svc); ++ if (lerr == LOCKDOWN_E_PASSWORD_PROTECTED) { ++ fprintf(stderr, "*** Device is passcode protected, enter passcode on the device to continue ***\n"); ++ while (1) { ++ lerr = lockdownd_start_service(lockdown, SYSLOG_RELAY_SERVICE_NAME, &svc); ++ if (lerr != LOCKDOWN_E_PASSWORD_PROTECTED) { ++ break; ++ } ++ sleep(1); ++ } ++ } ++ if (lerr != LOCKDOWN_E_SUCCESS) { ++ fprintf(stderr, "ERROR: Could not connect to lockdownd: %d\n", lerr); ++ idevice_free(device); ++ device = NULL; ++ return -1; ++ } ++ lockdownd_client_free(lockdown); ++ ++ /* connect to syslog_relay service */ + syslog_relay_error_t serr = SYSLOG_RELAY_E_UNKNOWN_ERROR; +- serr = syslog_relay_client_start_service(device, &syslog, "idevicesyslog"); ++ serr = syslog_relay_client_new(device, svc, &syslog); ++ lockdownd_service_descriptor_free(svc); + if (serr != SYSLOG_RELAY_E_SUCCESS) { + fprintf(stderr, "ERROR: Could not start service com.apple.syslog_relay.\n"); + idevice_free(device); +-- +2.23.0 + + +From 739a34ce8c711f975151d2ae6ef1e575d0aed764 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Wed, 21 Mar 2018 14:35:23 +0100 +Subject: [PATCH 071/151] idevicediagnostics: Add HDMI to the list of valid + options for diagnostics command + +--- + tools/idevicediagnostics.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/idevicediagnostics.c b/tools/idevicediagnostics.c +index 8b6569d..2ea986f 100644 +--- a/tools/idevicediagnostics.c ++++ b/tools/idevicediagnostics.c +@@ -104,7 +104,7 @@ int main(int argc, char **argv) + cmd = CMD_DIAGNOSTICS; + /* read type */ + i++; +- if (!argv[i] || ((strcmp(argv[i], "All") != 0) && (strcmp(argv[i], "WiFi") != 0) && (strcmp(argv[i], "GasGauge") != 0) && (strcmp(argv[i], "NAND") != 0))) { ++ if (!argv[i] || ((strcmp(argv[i], "All") != 0) && (strcmp(argv[i], "WiFi") != 0) && (strcmp(argv[i], "GasGauge") != 0) && (strcmp(argv[i], "NAND") != 0) && (strcmp(argv[i], "HDMI") != 0))) { + if (argv[i] == NULL) { + cmd_arg = strdup("All"); + continue; +-- +2.23.0 + + +From f37b592788bffcb9a70d211aef8b1f84751114ca Mon Sep 17 00:00:00 2001 +From: Robert Gadbois +Date: Wed, 21 Mar 2018 15:06:22 +0100 +Subject: [PATCH 072/151] idevicediagnostics: Add ioregentry command to query + device IORegistry by entry + +Starting with iOS 9.1, querying IORegistry by plane stopped working. This +commit will add a new command that allows querying by entry that will allow +gathering data for devices with newer iOS versions again (including iOS 11). +--- + tools/idevicediagnostics.c | 23 ++++++++++++++++++++++- + 1 file changed, 22 insertions(+), 1 deletion(-) + +diff --git a/tools/idevicediagnostics.c b/tools/idevicediagnostics.c +index 2ea986f..66e192f 100644 +--- a/tools/idevicediagnostics.c ++++ b/tools/idevicediagnostics.c +@@ -40,7 +40,8 @@ enum cmd_mode { + CMD_SHUTDOWN, + CMD_DIAGNOSTICS, + CMD_MOBILEGESTALT, +- CMD_IOREGISTRY ++ CMD_IOREGISTRY, ++ CMD_IOREGISTRY_ENTRY + }; + + static void print_xml(plist_t node) +@@ -156,6 +157,15 @@ int main(int argc, char **argv) + } + continue; + } ++ else if (!strcmp(argv[i], "ioregentry")) { ++ cmd = CMD_IOREGISTRY_ENTRY; ++ /* read key */ ++ i++; ++ if (argv[i]) { ++ cmd_arg = strdup(argv[i]); ++ } ++ continue; ++ } + else { + print_usage(argc, argv); + return 0; +@@ -232,6 +242,16 @@ int main(int argc, char **argv) + printf("Unable to query mobilegestalt keys.\n"); + } + break; ++ case CMD_IOREGISTRY_ENTRY: ++ if (diagnostics_relay_query_ioregistry_entry(diagnostics_client, cmd_arg == NULL ? "": cmd_arg, "", &node) == DIAGNOSTICS_RELAY_E_SUCCESS) { ++ if (node) { ++ print_xml(node); ++ result = EXIT_SUCCESS; ++ } ++ } else { ++ printf("Unable to retrieve IORegistry from device.\n"); ++ } ++ break; + case CMD_IOREGISTRY: + if (diagnostics_relay_query_ioregistry_plane(diagnostics_client, cmd_arg == NULL ? "": cmd_arg, &node) == DIAGNOSTICS_RELAY_E_SUCCESS) { + if (node) { +@@ -292,6 +312,7 @@ void print_usage(int argc, char **argv) + printf(" diagnostics [TYPE]\t\tprint diagnostics information from device by TYPE (All, WiFi, GasGauge, NAND)\n"); + printf(" mobilegestalt KEY [...]\tprint mobilegestalt keys passed as arguments seperated by a space.\n"); + printf(" ioreg [PLANE]\t\t\tprint IORegistry of device, optionally by PLANE (IODeviceTree, IOPower, IOService) (iOS 5+ only)\n"); ++ printf(" ioregentry [KEY]\t\tprint IORegistry entry of device (AppleARMPMUCharger, ASPStorage, ...) (iOS 5+ only)\n"); + printf(" shutdown\t\t\tshutdown device\n"); + printf(" restart\t\t\trestart device\n"); + printf(" sleep\t\t\t\tput device into sleep mode (disconnects from host)\n\n"); +-- +2.23.0 + + +From 90d4399c93ad73871db02eec115f0ac7f6137213 Mon Sep 17 00:00:00 2001 +From: Bastien Nocera +Date: Fri, 15 Sep 2017 16:00:09 +0200 +Subject: [PATCH 073/151] userpref: [GnuTLS] Fix 3.6.0 SHA1 compatibility + +Verification will fail if a special flag is not passed. Use +gnutls_x509_crt_sign2() instead of gnutls_x509_crt_sign() to make +sure that passing this flag works in 3.6.0 and stays working with +3.6.1. +--- + common/userpref.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/common/userpref.c b/common/userpref.c +index 3ae503a..f496fee 100644 +--- a/common/userpref.c ++++ b/common/userpref.c +@@ -603,7 +603,7 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da + gnutls_x509_crt_set_ca_status(root_cert, 1); + gnutls_x509_crt_set_activation_time(root_cert, time(NULL)); + gnutls_x509_crt_set_expiration_time(root_cert, time(NULL) + (60 * 60 * 24 * 365 * 10)); +- gnutls_x509_crt_sign(root_cert, root_cert, root_privkey); ++ gnutls_x509_crt_sign2(root_cert, root_cert, root_privkey, GNUTLS_DIG_SHA1, 0); + + gnutls_x509_crt_set_key(host_cert, host_privkey); + gnutls_x509_crt_set_serial(host_cert, "\x00", 1); +@@ -612,7 +612,7 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da + gnutls_x509_crt_set_key_usage(host_cert, GNUTLS_KEY_KEY_ENCIPHERMENT | GNUTLS_KEY_DIGITAL_SIGNATURE); + gnutls_x509_crt_set_activation_time(host_cert, time(NULL)); + gnutls_x509_crt_set_expiration_time(host_cert, time(NULL) + (60 * 60 * 24 * 365 * 10)); +- gnutls_x509_crt_sign(host_cert, root_cert, root_privkey); ++ gnutls_x509_crt_sign2(host_cert, root_cert, root_privkey, GNUTLS_DIG_SHA1, 0); + + /* export to PEM format */ + size_t root_key_export_size = 0; +@@ -720,7 +720,7 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da + } + + gnutls_x509_crt_set_key_usage(dev_cert, GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT); +- gnutls_error = gnutls_x509_crt_sign(dev_cert, root_cert, root_privkey); ++ gnutls_error = gnutls_x509_crt_sign2(dev_cert, root_cert, root_privkey, GNUTLS_DIG_SHA1, 0); + if (GNUTLS_E_SUCCESS == gnutls_error) { + /* if everything went well, export in PEM format */ + size_t export_size = 0; +-- +2.23.0 + + +From 99f4a332bbfa6886e300318381cb9efa972ca0ac Mon Sep 17 00:00:00 2001 +From: Bastien Nocera +Date: Fri, 15 Sep 2017 16:02:42 +0200 +Subject: [PATCH 074/151] userpref: [GnuTLS] Use valid serial for >= 3.6.0 + +Another change in 3.6.0 is that a serial of '\0' is not valid anymore. +Bump it to one. +--- + common/userpref.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/common/userpref.c b/common/userpref.c +index f496fee..be745cb 100644 +--- a/common/userpref.c ++++ b/common/userpref.c +@@ -598,7 +598,7 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da + + /* generate certificates */ + gnutls_x509_crt_set_key(root_cert, root_privkey); +- gnutls_x509_crt_set_serial(root_cert, "\x00", 1); ++ gnutls_x509_crt_set_serial(root_cert, "\x01", 1); + gnutls_x509_crt_set_version(root_cert, 3); + gnutls_x509_crt_set_ca_status(root_cert, 1); + gnutls_x509_crt_set_activation_time(root_cert, time(NULL)); +@@ -606,7 +606,7 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da + gnutls_x509_crt_sign2(root_cert, root_cert, root_privkey, GNUTLS_DIG_SHA1, 0); + + gnutls_x509_crt_set_key(host_cert, host_privkey); +- gnutls_x509_crt_set_serial(host_cert, "\x00", 1); ++ gnutls_x509_crt_set_serial(host_cert, "\x01", 1); + gnutls_x509_crt_set_version(host_cert, 3); + gnutls_x509_crt_set_ca_status(host_cert, 0); + gnutls_x509_crt_set_key_usage(host_cert, GNUTLS_KEY_KEY_ENCIPHERMENT | GNUTLS_KEY_DIGITAL_SIGNATURE); +@@ -703,7 +703,7 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da + if (GNUTLS_E_SUCCESS == gnutls_error) { + /* now generate device certificate */ + gnutls_x509_crt_set_key(dev_cert, fake_privkey); +- gnutls_x509_crt_set_serial(dev_cert, "\x00", 1); ++ gnutls_x509_crt_set_serial(dev_cert, "\x01", 1); + gnutls_x509_crt_set_version(dev_cert, 3); + gnutls_x509_crt_set_ca_status(dev_cert, 0); + gnutls_x509_crt_set_activation_time(dev_cert, time(NULL)); +-- +2.23.0 + + +From c7ead85cb9daabe26df467b16ddefbbc7b1d3f3c Mon Sep 17 00:00:00 2001 +From: Bastien Nocera +Date: Tue, 24 Jul 2018 14:17:40 +0200 +Subject: [PATCH 076/151] idevicebackup2: Fix fd leak in + mb2_copy_file_by_path() + +fd was leak in error path. +--- + tools/idevicebackup2.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/tools/idevicebackup2.c b/tools/idevicebackup2.c +index e6c1d3f..010e51d 100644 +--- a/tools/idevicebackup2.c ++++ b/tools/idevicebackup2.c +@@ -1150,6 +1150,7 @@ static void mb2_copy_file_by_path(const char *src, const char *dst) + /* open destination file */ + if ((to = fopen(dst, "wb")) == NULL) { + printf("Cannot open destination file '%s'.\n", dst); ++ fclose(from); + return; + } + +-- +2.23.0 + + +From 370a323148f691a5bb8f1d59b3c4aaf439f2d4b2 Mon Sep 17 00:00:00 2001 +From: Bastien Nocera +Date: Tue, 24 Jul 2018 14:21:10 +0200 +Subject: [PATCH 077/151] idevicebackup2: Fix potential memleak + +If either of dstpath or srcpath can be NULL, then make sure they get +freed irrespective of the other variable's value in +mb2_copy_directory_by_path() +--- + tools/idevicebackup2.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/tools/idevicebackup2.c b/tools/idevicebackup2.c +index 010e51d..84b8a61 100644 +--- a/tools/idevicebackup2.c ++++ b/tools/idevicebackup2.c +@@ -1204,10 +1204,12 @@ static void mb2_copy_directory_by_path(const char *src, const char *dst) + if (srcpath && dstpath) { + /* copy file */ + mb2_copy_file_by_path(srcpath, dstpath); ++ } + ++ if (srcpath) + free(srcpath); ++ if (dstpath) + free(dstpath); +- } + } + closedir(cur_dir); + } +-- +2.23.0 + + +From 6358b721c2f4dfea1d8f9f84346da30b458ec441 Mon Sep 17 00:00:00 2001 +From: Bastien Nocera +Date: Tue, 24 Jul 2018 14:24:56 +0200 +Subject: [PATCH 078/151] idevicedebugserverproxy: Fix possible use-after-free + +When creating a connection handler thread fails, and we close the +server_fd, do not loop back to the start of the loop trying to run +socket_accept() on a closed fd, but break out of the loop instead. +--- + tools/idevicedebugserverproxy.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/idevicedebugserverproxy.c b/tools/idevicedebugserverproxy.c +index f270cdc..56b1013 100644 +--- a/tools/idevicedebugserverproxy.c ++++ b/tools/idevicedebugserverproxy.c +@@ -364,7 +364,7 @@ int main(int argc, char *argv[]) + fprintf(stderr, "Could not start connection handler.\n"); + socket_shutdown(server_fd, SHUT_RDWR); + socket_close(server_fd); +- continue; ++ break; + } + } + +-- +2.23.0 + + +From e46d17cadb3dd1259b0ca78dc80fc06fbf10c516 Mon Sep 17 00:00:00 2001 +From: Bastien Nocera +Date: Tue, 24 Jul 2018 14:27:05 +0200 +Subject: [PATCH 079/151] ideviceimagemounter: Fix possible memleak in option + parsing + +If some arguments are passed multiple times, don't leak the memory used +for the value of the first arguments passed. +--- + tools/ideviceimagemounter.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/tools/ideviceimagemounter.c b/tools/ideviceimagemounter.c +index ad3222a..d56fa0c 100644 +--- a/tools/ideviceimagemounter.c ++++ b/tools/ideviceimagemounter.c +@@ -104,12 +104,16 @@ static void parse_opts(int argc, char **argv) + print_usage(argc, argv); + exit(2); + } ++ if (udid) ++ free(udid); + udid = strdup(optarg); + break; + case 'l': + list_mode = 1; + break; + case 't': ++ if (imagetype) ++ free(imagetype); + imagetype = strdup(optarg); + break; + case 'x': +-- +2.23.0 + + +From d7a2e04d2e7880c56116fd35489a7f98755501b7 Mon Sep 17 00:00:00 2001 +From: Bastien Nocera +Date: Tue, 24 Jul 2018 14:28:22 +0200 +Subject: [PATCH 080/151] idevicepair: Fix possible memleak in option parsing + +If some arguments are passed multiple times, don't leak the memory used +for the value of the first arguments passed. +--- + tools/idevicepair.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/tools/idevicepair.c b/tools/idevicepair.c +index f34369e..b6f0751 100644 +--- a/tools/idevicepair.c ++++ b/tools/idevicepair.c +@@ -104,6 +104,8 @@ static void parse_opts(int argc, char **argv) + print_usage(argc, argv); + exit(2); + } ++ if (udid) ++ free(udid); + udid = strdup(optarg); + break; + case 'd': +-- +2.23.0 + + +From a00b019c4421ce4937a45a0529d3e3b369876cef Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Mon, 3 Sep 2018 17:14:18 +0200 +Subject: [PATCH 081/151] idevicebackup2: Prevent lockdownd timeouts + +--- + tools/idevicebackup2.c | 69 +++++++++++++++++++++++------------------- + 1 file changed, 38 insertions(+), 31 deletions(-) + +diff --git a/tools/idevicebackup2.c b/tools/idevicebackup2.c +index 84b8a61..e4bcdb9 100644 +--- a/tools/idevicebackup2.c ++++ b/tools/idevicebackup2.c +@@ -293,18 +293,33 @@ static char* get_uuid() + return uuid; + } + +-static plist_t mobilebackup_factory_info_plist_new(const char* udid, idevice_t device, lockdownd_client_t lockdown, afc_client_t afc) ++static plist_t mobilebackup_factory_info_plist_new(const char* udid, idevice_t device, afc_client_t afc) + { + /* gather data from lockdown */ + plist_t value_node = NULL; + plist_t root_node = NULL; ++ plist_t itunes_settings = NULL; ++ plist_t min_itunes_version = NULL; + char *udid_uppercase = NULL; + ++ lockdownd_client_t lockdown = NULL; ++ if (lockdownd_client_new_with_handshake(device, &lockdown, "idevicebackup2") != LOCKDOWN_E_SUCCESS) { ++ return NULL; ++ } ++ + plist_t ret = plist_new_dict(); + + /* get basic device information in one go */ + lockdownd_get_value(lockdown, NULL, NULL, &root_node); + ++ /* get iTunes settings */ ++ lockdownd_get_value(lockdown, "com.apple.iTunes", NULL, &itunes_settings); ++ ++ /* get minimum iTunes version */ ++ lockdownd_get_value(lockdown, "com.apple.mobile.iTunes", "MinITunesVersion", &min_itunes_version); ++ ++ lockdownd_client_free(lockdown); ++ + /* get a list of installed user applications */ + plist_t app_dict = plist_new_dict(); + plist_t installed_apps = plist_new_array(); +@@ -325,7 +340,6 @@ static plist_t mobilebackup_factory_info_plist_new(const char* udid, idevice_t d + if (apps && (plist_get_node_type(apps) == PLIST_ARRAY)) { + uint32_t app_count = plist_array_get_size(apps); + uint32_t i; +- time_t starttime = time(NULL); + for (i = 0; i < app_count; i++) { + plist_t app_entry = plist_array_get_item(apps, i); + plist_t bundle_id = plist_dict_get_item(app_entry, "CFBundleIdentifier"); +@@ -353,11 +367,6 @@ static plist_t mobilebackup_factory_info_plist_new(const char* udid, idevice_t d + } + free(bundle_id_str); + } +- if ((time(NULL) - starttime) > 5) { +- // make sure our lockdown connection doesn't time out in case this takes longer +- lockdownd_query_type(lockdown, NULL); +- starttime = time(NULL); +- } + } + } + plist_free(apps); +@@ -470,20 +479,17 @@ static plist_t mobilebackup_factory_info_plist_new(const char* udid, idevice_t d + } + plist_dict_set_item(ret, "iTunes Files", files); + +- plist_t itunes_settings = NULL; +- lockdownd_get_value(lockdown, "com.apple.iTunes", NULL, &itunes_settings); + plist_dict_set_item(ret, "iTunes Settings", itunes_settings ? itunes_settings : plist_new_dict()); + + /* since we usually don't have iTunes, let's get the minimum required iTunes version from the device */ +- value_node = NULL; +- lockdownd_get_value(lockdown, "com.apple.mobile.iTunes", "MinITunesVersion", &value_node); +- if (value_node) { +- plist_dict_set_item(ret, "iTunes Version", plist_copy(value_node)); +- plist_free(value_node); ++ if (min_itunes_version) { ++ plist_dict_set_item(ret, "iTunes Version", plist_copy(min_itunes_version)); + } else { + plist_dict_set_item(ret, "iTunes Version", plist_new_string("10.0.1")); + } + ++ plist_free(itunes_settings); ++ plist_free(min_itunes_version); + plist_free(root_node); + + return ret; +@@ -1632,6 +1638,17 @@ int main(int argc, char *argv[]) + return -1; + } + ++ uint8_t willEncrypt = 0; ++ node_tmp = NULL; ++ lockdownd_get_value(lockdown, "com.apple.mobile.backup", "WillEncrypt", &node_tmp); ++ if (node_tmp) { ++ if (plist_get_node_type(node_tmp) == PLIST_BOOLEAN) { ++ plist_get_bool_val(node_tmp, &willEncrypt); ++ } ++ plist_free(node_tmp); ++ node_tmp = NULL; ++ } ++ + /* start notification_proxy */ + np_client_t np = NULL; + ldret = lockdownd_start_service(lockdown, NP_SERVICE_NAME, &service); +@@ -1669,6 +1686,8 @@ int main(int argc, char *argv[]) + /* start mobilebackup service and retrieve port */ + mobilebackup2_client_t mobilebackup2 = NULL; + ldret = lockdownd_start_service_with_escrow_bag(lockdown, MOBILEBACKUP2_SERVICE_NAME, &service); ++ lockdownd_client_free(lockdown); ++ lockdown = NULL; + if ((ldret == LOCKDOWN_E_SUCCESS) && service && service->port) { + PRINT_VERBOSE(1, "Started \"%s\" service on port %d.\n", MOBILEBACKUP2_SERVICE_NAME, service->port); + mobilebackup2_client_new(device, service, &mobilebackup2); +@@ -1745,16 +1764,6 @@ int main(int argc, char *argv[]) + cmd = CMD_LEAVE; + } + } +- uint8_t willEncrypt = 0; +- node_tmp = NULL; +- lockdownd_get_value(lockdown, "com.apple.mobile.backup", "WillEncrypt", &node_tmp); +- if (node_tmp) { +- if (plist_get_node_type(node_tmp) == PLIST_BOOLEAN) { +- plist_get_bool_val(node_tmp, &willEncrypt); +- } +- plist_free(node_tmp); +- node_tmp = NULL; +- } + + checkpoint: + +@@ -1798,7 +1807,11 @@ checkpoint: + plist_free(info_plist); + info_plist = NULL; + } +- info_plist = mobilebackup_factory_info_plist_new(udid, device, lockdown, afc); ++ info_plist = mobilebackup_factory_info_plist_new(udid, device, afc); ++ if (!info_plist) { ++ fprintf(stderr, "Failed to generate Info.plist - aborting\n"); ++ cmd = CMD_LEAVE; ++ } + remove_file(info_path); + plist_write_to_filename(info_plist, info_path, PLIST_FORMAT_XML); + free(info_path); +@@ -1988,12 +2001,6 @@ checkpoint: + break; + } + +- /* close down the lockdown connection as it is no longer needed */ +- if (lockdown) { +- lockdownd_client_free(lockdown); +- lockdown = NULL; +- } +- + if (cmd != CMD_LEAVE) { + /* reset operation success status */ + int operation_ok = 0; +-- +2.23.0 + + +From fb71aeef10488ed7b0e60a1c8a553193301428c0 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Mon, 3 Sep 2018 17:29:53 +0200 +Subject: [PATCH 082/151] idevicebackup2: Make sure iTunesSettings are + correctly stored in Info.plist (i.e. not freed before writing) + +--- + tools/idevicebackup2.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/idevicebackup2.c b/tools/idevicebackup2.c +index e4bcdb9..7fb67df 100644 +--- a/tools/idevicebackup2.c ++++ b/tools/idevicebackup2.c +@@ -479,7 +479,7 @@ static plist_t mobilebackup_factory_info_plist_new(const char* udid, idevice_t d + } + plist_dict_set_item(ret, "iTunes Files", files); + +- plist_dict_set_item(ret, "iTunes Settings", itunes_settings ? itunes_settings : plist_new_dict()); ++ plist_dict_set_item(ret, "iTunes Settings", itunes_settings ? plist_copy(itunes_settings) : plist_new_dict()); + + /* since we usually don't have iTunes, let's get the minimum required iTunes version from the device */ + if (min_itunes_version) { +-- +2.23.0 + + +From 05fefa6aeff45fc84665e8427444295d8414df98 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Sat, 29 Sep 2018 22:56:14 +0200 +Subject: [PATCH 083/151] idevice: Add usbmux device id (handle/mux id) to + internal data structure + +--- + include/libimobiledevice/libimobiledevice.h | 2 +- + src/idevice.c | 19 ++++++------------- + src/idevice.h | 1 + + 3 files changed, 8 insertions(+), 14 deletions(-) + +diff --git a/include/libimobiledevice/libimobiledevice.h b/include/libimobiledevice/libimobiledevice.h +index 68eb511..5ec1a6d 100644 +--- a/include/libimobiledevice/libimobiledevice.h ++++ b/include/libimobiledevice/libimobiledevice.h +@@ -253,7 +253,7 @@ idevice_error_t idevice_connection_get_fd(idevice_connection_t connection, int * + /* misc */ + + /** +- * Gets the handle of the device. Depends on the connection type. ++ * Gets the handle or (usbmux device id) of the device. + */ + idevice_error_t idevice_get_handle(idevice_t device, uint32_t *handle); + +diff --git a/src/idevice.c b/src/idevice.c +index ead9b86..cb9bb5c 100644 +--- a/src/idevice.c ++++ b/src/idevice.c +@@ -254,8 +254,9 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_new(idevice_t * device, const char + if (res > 0) { + idevice_t dev = (idevice_t) malloc(sizeof(struct idevice_private)); + dev->udid = strdup(muxdev.udid); ++ dev->mux_id = muxdev.handle; + dev->conn_type = CONNECTION_USBMUXD; +- dev->conn_data = (void*)(long)muxdev.handle; ++ dev->conn_data = NULL; + dev->version = 0; + *device = dev; + return IDEVICE_E_SUCCESS; +@@ -275,9 +276,6 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_free(idevice_t device) + + free(device->udid); + +- if (device->conn_type == CONNECTION_USBMUXD) { +- device->conn_data = 0; +- } + if (device->conn_data) { + free(device->conn_data); + } +@@ -292,7 +290,7 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connect(idevice_t device, uint16_t + } + + if (device->conn_type == CONNECTION_USBMUXD) { +- int sfd = usbmuxd_connect((uint32_t)(long)device->conn_data, port); ++ int sfd = usbmuxd_connect(device->mux_id, port); + if (sfd < 0) { + debug_info("ERROR: Connecting to usbmuxd failed: %d (%s)", sfd, strerror(-sfd)); + return IDEVICE_E_UNKNOWN_ERROR; +@@ -502,16 +500,11 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_get_fd(idevice_connectio + + LIBIMOBILEDEVICE_API idevice_error_t idevice_get_handle(idevice_t device, uint32_t *handle) + { +- if (!device) ++ if (!device || !handle) + return IDEVICE_E_INVALID_ARG; + +- if (device->conn_type == CONNECTION_USBMUXD) { +- *handle = (uint32_t)(long)device->conn_data; +- return IDEVICE_E_SUCCESS; +- } else { +- debug_info("Unknown connection type %d", device->conn_type); +- } +- return IDEVICE_E_UNKNOWN_ERROR; ++ *handle = device->mux_id; ++ return IDEVICE_E_SUCCESS; + } + + LIBIMOBILEDEVICE_API idevice_error_t idevice_get_udid(idevice_t device, char **udid) +diff --git a/src/idevice.h b/src/idevice.h +index e46a7e5..94e828b 100644 +--- a/src/idevice.h ++++ b/src/idevice.h +@@ -74,6 +74,7 @@ struct idevice_connection_private { + + struct idevice_private { + char *udid; ++ uint32_t mux_id; + enum connection_type conn_type; + void *conn_data; + int version; +-- +2.23.0 + + +From f1ee0fd8b2b1dd65c64f5a67e208efc708295caa Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Sat, 29 Sep 2018 22:59:25 +0200 +Subject: [PATCH 084/151] lockdown: Pass along usbmux device id when saving + pair records + +--- + common/userpref.c | 5 +++-- + common/userpref.h | 2 +- + configure.ac | 2 +- + src/lockdown.c | 3 ++- + src/lockdown.h | 1 + + 5 files changed, 8 insertions(+), 5 deletions(-) + +diff --git a/common/userpref.c b/common/userpref.c +index be745cb..0fa5b96 100644 +--- a/common/userpref.c ++++ b/common/userpref.c +@@ -273,19 +273,20 @@ userpref_error_t userpref_get_paired_udids(char ***list, unsigned int *count) + * Save a pair record for a device. + * + * @param udid The device UDID as given by the device ++ * @param device_id The usbmux device id (handle) of the connected device, or 0 + * @param pair_record The pair record to save + * + * @return 1 on success and 0 if no device record is given or if it has already + * been saved previously. + */ +-userpref_error_t userpref_save_pair_record(const char *udid, plist_t pair_record) ++userpref_error_t userpref_save_pair_record(const char *udid, uint32_t device_id, plist_t pair_record) + { + char* record_data = NULL; + uint32_t record_size = 0; + + plist_to_bin(pair_record, &record_data, &record_size); + +- int res = usbmuxd_save_pair_record(udid, record_data, record_size); ++ int res = usbmuxd_save_pair_record_with_device_id(udid, device_id, record_data, record_size); + + free(record_data); + +diff --git a/common/userpref.h b/common/userpref.h +index 84fea53..4ea630f 100644 +--- a/common/userpref.h ++++ b/common/userpref.h +@@ -64,7 +64,7 @@ typedef enum { + const char *userpref_get_config_dir(void); + int userpref_read_system_buid(char **system_buid); + userpref_error_t userpref_read_pair_record(const char *udid, plist_t *pair_record); +-userpref_error_t userpref_save_pair_record(const char *udid, plist_t pair_record); ++userpref_error_t userpref_save_pair_record(const char *udid, uint32_t device_id, plist_t pair_record); + userpref_error_t userpref_delete_pair_record(const char *udid); + + userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_data_t public_key); +diff --git a/configure.ac b/configure.ac +index e41baa3..ec210fc 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -18,7 +18,7 @@ dnl libtool versioning + LIBIMOBILEDEVICE_SO_VERSION=6:0:0 + + dnl Minimum package versions +-LIBUSBMUXD_VERSION=1.0.9 ++LIBUSBMUXD_VERSION=1.1.0 + LIBPLIST_VERSION=1.11 + LIBPLISTMM_VERSION=1.11 + +diff --git a/src/lockdown.c b/src/lockdown.c +index 9d6d17d..2492897 100644 +--- a/src/lockdown.c ++++ b/src/lockdown.c +@@ -668,6 +668,7 @@ LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_client_new(idevice_t device, lo + client_loc->parent = plistclient; + client_loc->ssl_enabled = 0; + client_loc->session_id = NULL; ++ client_loc->mux_id = device->mux_id; + + if (idevice_get_udid(device, &client_loc->udid) != IDEVICE_E_SUCCESS) { + debug_info("failed to get device udid."); +@@ -1001,7 +1002,7 @@ static lockdownd_error_t lockdownd_do_pair(lockdownd_client_t client, lockdownd_ + wifi_node = NULL; + } + +- userpref_save_pair_record(client->udid, pair_record_plist); ++ userpref_save_pair_record(client->udid, client->mux_id, pair_record_plist); + } + } + } else { +diff --git a/src/lockdown.h b/src/lockdown.h +index ab63e86..bf595df 100644 +--- a/src/lockdown.h ++++ b/src/lockdown.h +@@ -34,6 +34,7 @@ struct lockdownd_client_private { + char *session_id; + char *udid; + char *label; ++ uint32_t mux_id; + }; + + #endif +-- +2.23.0 + + +From b34e3435c21d06b3e5a4e7b5246fb6ddb6641a9f Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Mon, 1 Oct 2018 02:32:51 +0200 +Subject: [PATCH 085/151] tools: Remove length check on device UDID arguments + to support newer devices + +The 40 characters length check on the device UDID made newer devices unusable +with the libimobiledevice tools and was actually redundant since an invalid +UDID will always fail to resolve. This commit removes the length check +alltogether (but makes sure it is not an empty string ""). +--- + common/userpref.c | 53 +++++++++++++++----------------- + docs/idevice_id.1 | 2 +- + docs/idevicebackup.1 | 2 +- + docs/idevicebackup2.1 | 2 +- + docs/idevicecrashreport.1 | 2 +- + docs/idevicedate.1 | 2 +- + docs/idevicedebug.1 | 2 +- + docs/idevicedebugserverproxy.1 | 2 +- + docs/idevicediagnostics.1 | 2 +- + docs/ideviceenterrecovery.1 | 2 +- + docs/ideviceimagemounter.1 | 2 +- + docs/ideviceinfo.1 | 2 +- + docs/idevicename.1 | 2 +- + docs/idevicenotificationproxy.1 | 2 +- + docs/idevicepair.1 | 2 +- + docs/ideviceprovision.1 | 2 +- + docs/idevicescreenshot.1 | 2 +- + docs/idevicesyslog.1 | 2 +- + tools/idevice_id.c | 6 ++-- + tools/idevicebackup.c | 4 +-- + tools/idevicebackup2.c | 6 ++-- + tools/idevicecrashreport.c | 4 +-- + tools/idevicedate.c | 4 +-- + tools/idevicedebug.c | 4 +-- + tools/idevicedebugserverproxy.c | 4 +-- + tools/idevicediagnostics.c | 4 +-- + tools/ideviceenterrecovery.c | 4 +-- + tools/ideviceimagemounter.c | 25 +++++++-------- + tools/ideviceinfo.c | 4 +-- + tools/idevicename.c | 8 ++++- + tools/idevicenotificationproxy.c | 4 +-- + tools/idevicepair.c | 12 ++++---- + tools/ideviceprovision.c | 4 +-- + tools/idevicescreenshot.c | 4 +-- + tools/idevicesyslog.c | 4 +-- + 35 files changed, 95 insertions(+), 97 deletions(-) + +diff --git a/common/userpref.c b/common/userpref.c +index 0fa5b96..b985285 100644 +--- a/common/userpref.c ++++ b/common/userpref.c +@@ -208,14 +208,8 @@ int userpref_read_system_buid(char **system_buid) + */ + userpref_error_t userpref_get_paired_udids(char ***list, unsigned int *count) + { +- struct slist_t { +- char *name; +- void *next; +- }; + DIR *config_dir; + const char *config_path = NULL; +- struct slist_t *udids = NULL; +- unsigned int i; + unsigned int found = 0; + + if (!list || (list && *list)) { +@@ -226,41 +220,42 @@ userpref_error_t userpref_get_paired_udids(char ***list, unsigned int *count) + if (count) { + *count = 0; + } ++ *list = (char**)malloc(sizeof(char*)); + + config_path = userpref_get_config_dir(); + config_dir = opendir(config_path); + if (config_dir) { + struct dirent *entry; +- struct slist_t *listp = udids; + while ((entry = readdir(config_dir))) { +- char *ext = strstr(entry->d_name, USERPREF_CONFIG_EXTENSION); +- if (ext && ((ext - entry->d_name) == 40) && (strlen(entry->d_name) == (40 + strlen(ext)))) { +- struct slist_t *ne = (struct slist_t*)malloc(sizeof(struct slist_t)); +- ne->name = (char*)malloc(41); +- strncpy(ne->name, entry->d_name, 40); +- ne->name[40] = 0; +- ne->next = NULL; +- if (!listp) { +- listp = ne; +- udids = listp; +- } else { +- listp->next = ne; +- listp = listp->next; ++ if (strcmp(entry->d_name, USERPREF_CONFIG_FILE) == 0) { ++ /* ignore SystemConfiguration.plist */ ++ continue; ++ } ++ char *ext = strrchr(entry->d_name, '.'); ++ if (ext && (strcmp(ext, USERPREF_CONFIG_EXTENSION) == 0)) { ++ size_t len = strlen(entry->d_name) - strlen(USERPREF_CONFIG_EXTENSION); ++ char **newlist = (char**)realloc(*list, sizeof(char*) * (found+2)); ++ if (!newlist) { ++ fprintf(stderr, "ERROR: Out of memory\n"); ++ break; ++ } ++ *list = newlist; ++ char *tmp = (char*)malloc(len+1); ++ if (tmp) { ++ strncpy(tmp, entry->d_name, len); ++ tmp[len] = '\0'; ++ } ++ (*list)[found] = tmp; ++ if (!tmp) { ++ fprintf(stderr, "ERROR: Out of memory\n"); ++ break; + } + found++; + } + } + closedir(config_dir); + } +- *list = (char**)malloc(sizeof(char*) * (found+1)); +- i = 0; +- while (udids) { +- (*list)[i++] = udids->name; +- struct slist_t *old = udids; +- udids = udids->next; +- free(old); +- } +- (*list)[i] = NULL; ++ (*list)[found] = NULL; + + if (count) { + *count = found; +diff --git a/docs/idevice_id.1 b/docs/idevice_id.1 +index cdc5342..e223dcb 100644 +--- a/docs/idevice_id.1 ++++ b/docs/idevice_id.1 +@@ -8,7 +8,7 @@ idevice_id \- Prints device name or a list of attached devices. + .SH DESCRIPTION + + Prints device name or a list of attached devices. +-The UDID is a 40-digit hexadecimal number of the device ++UDID is the unique device identifier of the device + for which the name should be retrieved. + + .SH OPTIONS +diff --git a/docs/idevicebackup.1 b/docs/idevicebackup.1 +index a9330e0..517ca2a 100644 +--- a/docs/idevicebackup.1 ++++ b/docs/idevicebackup.1 +@@ -12,7 +12,7 @@ Create or restore backup from the current or specified directory. + .SH OPTIONS + .TP + .B \-u, \-\-udid UDID +-target specific device by its 40-digit device UDID. ++target specific device by UDID. + .TP + .B \-d, \-\-debug + enable communication debugging. +diff --git a/docs/idevicebackup2.1 b/docs/idevicebackup2.1 +index 1b50a2b..6c40929 100644 +--- a/docs/idevicebackup2.1 ++++ b/docs/idevicebackup2.1 +@@ -12,7 +12,7 @@ Create or restore backup from the current or specified directory. + .SH OPTIONS + .TP + .B \-u, \-\-udid UDID +-target specific device by its 40-digit device UDID. ++target specific device by UDID. + .TP + .B \-s, \-\-source UDID + use backup data from device specified by UDID. +diff --git a/docs/idevicecrashreport.1 b/docs/idevicecrashreport.1 +index 24015d3..a3742e7 100644 +--- a/docs/idevicecrashreport.1 ++++ b/docs/idevicecrashreport.1 +@@ -25,7 +25,7 @@ copy but do not remove crash reports from device. + enable communication debugging. + .TP + .B \-u, \-\-udid UDID +-target specific device by its 40-digit device UDID. ++target specific device by UDID. + .TP + .B \-h, \-\-help + prints usage information. +diff --git a/docs/idevicedate.1 b/docs/idevicedate.1 +index aa77df6..adb091a 100644 +--- a/docs/idevicedate.1 ++++ b/docs/idevicedate.1 +@@ -15,7 +15,7 @@ Simple utility to manage the clock on a device. + enable communication debugging. + .TP + .B \-u, \-\-udid UDID +-target specific device by its 40-digit device UDID. ++target specific device by UDID. + .TP + .B \-s, \-\-set TIMESTAMP + set UTC time described by TIMESTAMP +diff --git a/docs/idevicedebug.1 b/docs/idevicedebug.1 +index daa3c0c..2024842 100644 +--- a/docs/idevicedebug.1 ++++ b/docs/idevicedebug.1 +@@ -17,7 +17,7 @@ stdout/stderr of the process. + set environment variable NAME to VALUE. + .TP + .B \-u, \-\-udid UDID +-target specific device by its 40-digit device UDID. ++target specific device by UDID. + .TP + .B \-d, \-\-debug + enable communication debugging. +diff --git a/docs/idevicedebugserverproxy.1 b/docs/idevicedebugserverproxy.1 +index 669806a..e2372e6 100644 +--- a/docs/idevicedebugserverproxy.1 ++++ b/docs/idevicedebugserverproxy.1 +@@ -17,7 +17,7 @@ The developer disk image needs to be mounted for this service to be available. + .SH OPTIONS + .TP + .B \-u, \-\-udid UDID +-target specific device by its 40-digit device UDID. ++target specific device by UDID. + .TP + .B \-d, \-\-debug + enable communication debugging. +diff --git a/docs/idevicediagnostics.1 b/docs/idevicediagnostics.1 +index 460c17f..8a9b947 100644 +--- a/docs/idevicediagnostics.1 ++++ b/docs/idevicediagnostics.1 +@@ -16,7 +16,7 @@ iOS 5 and later. + .SH OPTIONS + .TP + .B \-u, \-\-udid UDID +-target specific device by its 40-digit device UDID. ++target specific device by UDID. + .TP + .B \-d, \-\-debug + enable communication debugging. +diff --git a/docs/ideviceenterrecovery.1 b/docs/ideviceenterrecovery.1 +index feea733..cbceb36 100644 +--- a/docs/ideviceenterrecovery.1 ++++ b/docs/ideviceenterrecovery.1 +@@ -7,7 +7,7 @@ ideviceenterrecovery \- Make a device enter recovery mode. + + .SH DESCRIPTION + +-Makes a device with the supplied 40-digit UDID enter recovery mode immediately. ++Makes a device with the supplied UDID enter recovery mode immediately. + + .SH OPTIONS + .TP +diff --git a/docs/ideviceimagemounter.1 b/docs/ideviceimagemounter.1 +index 4afdca6..322bd34 100644 +--- a/docs/ideviceimagemounter.1 ++++ b/docs/ideviceimagemounter.1 +@@ -15,7 +15,7 @@ Mounts the specified disk image on the device. + enable communication debugging. + .TP + .B \-u, \-\-udid UDID +-target specific device by its 40-digit device UDID. ++target specific device by UDID. + .TP + .B \-l, \-\-list + list mount information +diff --git a/docs/ideviceinfo.1 b/docs/ideviceinfo.1 +index f61c713..d4ecbf0 100644 +--- a/docs/ideviceinfo.1 ++++ b/docs/ideviceinfo.1 +@@ -15,7 +15,7 @@ Show information about the first connected device. + enable communication debugging. + .TP + .B \-u, \-\-udid UDID +-target specific device by its 40-digit device UDID. ++target specific device by UDID. + .TP + .B \-q, \-\-domain NAME + set domain of query to NAME. Default: None. +diff --git a/docs/idevicename.1 b/docs/idevicename.1 +index 67897f1..ee7cd02 100644 +--- a/docs/idevicename.1 ++++ b/docs/idevicename.1 +@@ -21,7 +21,7 @@ is given the device name will be set to the name specified. + enable communication debugging. + .TP + .B \-u, \-\-udid UDID +-target specific device by its 40-digit device UDID. ++target specific device by UDID. + .TP + .B \-h, \-\-help + prints usage information +diff --git a/docs/idevicenotificationproxy.1 b/docs/idevicenotificationproxy.1 +index 75bf6b1..19cf02e 100644 +--- a/docs/idevicenotificationproxy.1 ++++ b/docs/idevicenotificationproxy.1 +@@ -12,7 +12,7 @@ Post or observe notifications on an iOS device from the command line. + .SH OPTIONS + .TP + .B \-u, \-\-udid UDID +-target specific device by its 40-digit device UDID. ++target specific device by UDID. + .TP + .B \-d, \-\-debug + enable communication debugging. +diff --git a/docs/idevicepair.1 b/docs/idevicepair.1 +index e9916b3..5c567ee 100644 +--- a/docs/idevicepair.1 ++++ b/docs/idevicepair.1 +@@ -12,7 +12,7 @@ Manage host pairings with devices and usbmuxd. + .SH OPTIONS + .TP + .B \-u, \-\-udid UDID +-target specific device by its 40-digit device UDID. ++target specific device by UDID. + .TP + .B \-d, \-\-debug + enable communication debugging. +diff --git a/docs/ideviceprovision.1 b/docs/ideviceprovision.1 +index b79ea82..5f312a5 100644 +--- a/docs/ideviceprovision.1 ++++ b/docs/ideviceprovision.1 +@@ -12,7 +12,7 @@ Manage provisioning profiles on a device. + .SH OPTIONS + .TP + .B \-u, \-\-udid UDID +-target specific device by its 40-digit device UDID. ++target specific device by UDID. + .TP + .B \-x, \-\-xml + print XML output when using the 'dump' command. +diff --git a/docs/idevicescreenshot.1 b/docs/idevicescreenshot.1 +index c2b9619..7b6794c 100644 +--- a/docs/idevicescreenshot.1 ++++ b/docs/idevicescreenshot.1 +@@ -22,7 +22,7 @@ the screenshotr service is not available. + enable communication debugging. + .TP + .B \-u, \-\-udid UDID +-target specific device by its 40-digit device UDID. ++target specific device by UDID. + .TP + .B \-h, \-\-help + prints usage information +diff --git a/docs/idevicesyslog.1 b/docs/idevicesyslog.1 +index 4230461..aa24339 100644 +--- a/docs/idevicesyslog.1 ++++ b/docs/idevicesyslog.1 +@@ -15,7 +15,7 @@ Relay syslog of a connected device. + enable communication debugging. + .TP + .B \-u, \-\-udid UDID +-target specific device by its 40-digit device UDID ++target specific device by UDID. + .TP + .B \-h, \-\-help + prints usage information. +diff --git a/tools/idevice_id.c b/tools/idevice_id.c +index 6f020ff..558dcbe 100644 +--- a/tools/idevice_id.c ++++ b/tools/idevice_id.c +@@ -40,7 +40,7 @@ static void print_usage(int argc, char **argv) + name = strrchr(argv[0], '/'); + printf("Usage: %s [OPTIONS] [UDID]\n", (name ? name + 1: argv[0])); + printf("Prints device name or a list of attached devices.\n\n"); +- printf(" The UDID is a 40-digit hexadecimal number of the device\n"); ++ printf(" UDID is the unique device identifier of the device\n"); + printf(" for which the name should be retrieved.\n\n"); + printf(" -l, --list\t\tlist UDID of all attached devices\n"); + printf(" -d, --debug\t\tenable communication debugging\n"); +@@ -79,7 +79,7 @@ int main(int argc, char **argv) + /* check if udid was passed */ + if (mode == MODE_SHOW_ID) { + i--; +- if (!argv[i] || (strlen(argv[i]) != 40)) { ++ if (argc < 2 || !argv[i] || !*argv[i]) { + print_usage(argc, argv); + return 0; + } +@@ -90,7 +90,7 @@ int main(int argc, char **argv) + case MODE_SHOW_ID: + idevice_new(&device, udid); + if (!device) { +- fprintf(stderr, "ERROR: No device with UDID=%s attached.\n", udid); ++ fprintf(stderr, "ERROR: No device with UDID %s attached.\n", udid); + return -2; + } + +diff --git a/tools/idevicebackup.c b/tools/idevicebackup.c +index 7e825de..cd69bcc 100644 +--- a/tools/idevicebackup.c ++++ b/tools/idevicebackup.c +@@ -671,7 +671,7 @@ static void print_usage(int argc, char **argv) + printf(" restore\tRestores a device backup from DIRECTORY.\n\n"); + printf("options:\n"); + printf(" -d, --debug\t\tenable communication debugging\n"); +- printf(" -u, --udid UDID\ttarget specific device by its 40-digit device UDID\n"); ++ printf(" -u, --udid UDID\ttarget specific device by UDID\n"); + printf(" -h, --help\t\tprints usage information\n"); + printf("\n"); + printf("Homepage: <" PACKAGE_URL ">\n"); +@@ -715,7 +715,7 @@ int main(int argc, char *argv[]) + } + else if (!strcmp(argv[i], "-u") || !strcmp(argv[i], "--udid")) { + i++; +- if (!argv[i] || (strlen(argv[i]) != 40)) { ++ if (!argv[i] || !*argv[i]) { + print_usage(argc, argv); + return 0; + } +diff --git a/tools/idevicebackup2.c b/tools/idevicebackup2.c +index 7fb67df..6d4785b 100644 +--- a/tools/idevicebackup2.c ++++ b/tools/idevicebackup2.c +@@ -1323,7 +1323,7 @@ static void print_usage(int argc, char **argv) + printf("\n"); + printf("options:\n"); + printf(" -d, --debug\t\tenable communication debugging\n"); +- printf(" -u, --udid UDID\ttarget specific device by its 40-digit device UDID\n"); ++ printf(" -u, --udid UDID\ttarget specific device by UDID\n"); + printf(" -s, --source UDID\tuse backup data from device specified by UDID\n"); + printf(" -i, --interactive\trequest passwords interactively\n"); + printf(" -h, --help\t\tprints usage information\n"); +@@ -1369,7 +1369,7 @@ int main(int argc, char *argv[]) + } + else if (!strcmp(argv[i], "-u") || !strcmp(argv[i], "--udid")) { + i++; +- if (!argv[i] || (strlen(argv[i]) != 40)) { ++ if (!argv[i] || !*argv[i]) { + print_usage(argc, argv); + return -1; + } +@@ -1378,7 +1378,7 @@ int main(int argc, char *argv[]) + } + else if (!strcmp(argv[i], "-s") || !strcmp(argv[i], "--source")) { + i++; +- if (!argv[i] || (strlen(argv[i]) != 40)) { ++ if (!argv[i] || !*argv[i]) { + print_usage(argc, argv); + return -1; + } +diff --git a/tools/idevicecrashreport.c b/tools/idevicecrashreport.c +index 4d7f41c..e05d506 100644 +--- a/tools/idevicecrashreport.c ++++ b/tools/idevicecrashreport.c +@@ -301,7 +301,7 @@ static void print_usage(int argc, char **argv) + printf(" -e, --extract\t\textract raw crash report into separate '.crash' file\n"); + printf(" -k, --keep\t\tcopy but do not remove crash reports from device\n"); + printf(" -d, --debug\t\tenable communication debugging\n"); +- printf(" -u, --udid UDID\ttarget specific device by its 40-digit device UDID\n"); ++ printf(" -u, --udid UDID\ttarget specific device by UDID\n"); + printf(" -h, --help\t\tprints usage information\n"); + printf("\n"); + printf("Homepage: <" PACKAGE_URL ">\n"); +@@ -327,7 +327,7 @@ int main(int argc, char* argv[]) { + } + else if (!strcmp(argv[i], "-u") || !strcmp(argv[i], "--udid")) { + i++; +- if (!argv[i] || (strlen(argv[i]) != 40)) { ++ if (!argv[i] || !*argv[i]) { + print_usage(argc, argv); + return 0; + } +diff --git a/tools/idevicedate.c b/tools/idevicedate.c +index 97243bb..2676880 100644 +--- a/tools/idevicedate.c ++++ b/tools/idevicedate.c +@@ -50,7 +50,7 @@ static void print_usage(int argc, char **argv) + printf("NOTE: Setting the time on iOS 6 and later is only supported\n"); + printf(" in the setup wizard screens before device activation.\n\n"); + printf(" -d, --debug\t\tenable communication debugging\n"); +- printf(" -u, --udid UDID\ttarget specific device by its 40-digit device UDID\n"); ++ printf(" -u, --udid UDID\ttarget specific device by UDID\n"); + printf(" -s, --set TIMESTAMP\tset UTC time described by TIMESTAMP\n"); + printf(" -c, --sync\t\tset time of device to current system time\n"); + printf(" -h, --help\t\tprints usage information\n"); +@@ -84,7 +84,7 @@ int main(int argc, char *argv[]) + } + else if (!strcmp(argv[i], "-u") || !strcmp(argv[i], "--udid")) { + i++; +- if (!argv[i] || (strlen(argv[i]) != 40)) { ++ if (!argv[i] || !*argv[i]) { + print_usage(argc, argv); + return 0; + } +diff --git a/tools/idevicedebug.c b/tools/idevicedebug.c +index f18254a..c7508e3 100644 +--- a/tools/idevicedebug.c ++++ b/tools/idevicedebug.c +@@ -188,7 +188,7 @@ static void print_usage(int argc, char **argv) + printf("\n"); + printf(" The following OPTIONS are accepted:\n"); + printf(" -e, --env NAME=VALUE\tset environment variable NAME to VALUE\n"); +- printf(" -u, --udid UDID\ttarget specific device by its 40-digit device UDID\n"); ++ printf(" -u, --udid UDID\ttarget specific device by UDID\n"); + printf(" -d, --debug\t\tenable communication debugging\n"); + printf(" -h, --help\t\tprints usage information\n"); + printf("\n"); +@@ -233,7 +233,7 @@ int main(int argc, char *argv[]) + continue; + } else if (!strcmp(argv[i], "-u") || !strcmp(argv[i], "--udid")) { + i++; +- if (!argv[i] || (strlen(argv[i]) != 40)) { ++ if (!argv[i] || !*argv[i]) { + print_usage(argc, argv); + res = 0; + goto cleanup; +diff --git a/tools/idevicedebugserverproxy.c b/tools/idevicedebugserverproxy.c +index 56b1013..0b0419b 100644 +--- a/tools/idevicedebugserverproxy.c ++++ b/tools/idevicedebugserverproxy.c +@@ -71,7 +71,7 @@ static void print_usage(int argc, char **argv) + printf("Usage: %s [OPTIONS] \n", (name ? name + 1: argv[0])); + printf("Proxy debugserver connection from device to a local socket at PORT.\n\n"); + printf(" -d, --debug\t\tenable communication debugging\n"); +- printf(" -u, --udid UDID\ttarget specific device by its 40-digit device UDID\n"); ++ printf(" -u, --udid UDID\ttarget specific device by UDID\n"); + printf(" -h, --help\t\tprints usage information\n"); + printf("\n"); + printf("Homepage: <" PACKAGE_URL ">\n"); +@@ -280,7 +280,7 @@ int main(int argc, char *argv[]) + } + else if (!strcmp(argv[i], "-u") || !strcmp(argv[i], "--udid")) { + i++; +- if (!argv[i] || (strlen(argv[i]) != 40)) { ++ if (!argv[i] || !*argv[i]) { + print_usage(argc, argv); + return 0; + } +diff --git a/tools/idevicediagnostics.c b/tools/idevicediagnostics.c +index 66e192f..8c32854 100644 +--- a/tools/idevicediagnostics.c ++++ b/tools/idevicediagnostics.c +@@ -79,7 +79,7 @@ int main(int argc, char **argv) + } + else if (!strcmp(argv[i], "-u") || !strcmp(argv[i], "--udid")) { + i++; +- if (!argv[i] || (strlen(argv[i]) != 40)) { ++ if (!argv[i] || !*argv[i]) { + print_usage(argc, argv); + result = 0; + goto cleanup; +@@ -318,7 +318,7 @@ void print_usage(int argc, char **argv) + printf(" sleep\t\t\t\tput device into sleep mode (disconnects from host)\n\n"); + printf(" The following OPTIONS are accepted:\n"); + printf(" -d, --debug\t\tenable communication debugging\n"); +- printf(" -u, --udid UDID\ttarget specific device by its 40-digit device UDID\n"); ++ printf(" -u, --udid UDID\ttarget specific device by UDID\n"); + printf(" -h, --help\t\tprints usage information\n"); + printf("\n"); + printf("Homepage: <" PACKAGE_URL ">\n"); +diff --git a/tools/ideviceenterrecovery.c b/tools/ideviceenterrecovery.c +index 21c4ff6..69484cc 100644 +--- a/tools/ideviceenterrecovery.c ++++ b/tools/ideviceenterrecovery.c +@@ -37,7 +37,7 @@ static void print_usage(int argc, char **argv) + + name = strrchr(argv[0], '/'); + printf("Usage: %s [OPTIONS] UDID\n", (name ? name + 1: argv[0])); +- printf("Makes a device with the supplied 40-digit UDID enter recovery mode immediately.\n\n"); ++ printf("Makes a device with the supplied UDID enter recovery mode immediately.\n\n"); + printf(" -d, --debug\t\tenable communication debugging\n"); + printf(" -h, --help\t\tprints usage information\n"); + printf("\n"); +@@ -66,7 +66,7 @@ int main(int argc, char *argv[]) + } + + i--; +- if (!argv[i] || (strlen(argv[i]) != 40)) { ++ if (argc < 2 || !argv[i] || !*argv[i]) { + print_usage(argc, argv); + return 0; + } +diff --git a/tools/ideviceimagemounter.c b/tools/ideviceimagemounter.c +index d56fa0c..7101c7e 100644 +--- a/tools/ideviceimagemounter.c ++++ b/tools/ideviceimagemounter.c +@@ -63,7 +63,7 @@ static void print_usage(int argc, char **argv) + name = strrchr(argv[0], '/'); + printf("Usage: %s [OPTIONS] IMAGE_FILE IMAGE_SIGNATURE_FILE\n\n", (name ? name + 1: argv[0])); + printf("Mounts the specified disk image on the device.\n\n"); +- printf(" -u, --udid UDID\ttarget specific device by its 40-digit device UDID\n"); ++ printf(" -u, --udid UDID\ttarget specific device by UDID\n"); + printf(" -l, --list\t\tList mount information\n"); + printf(" -t, --imagetype\tImage type to use, default is 'Developer'\n"); + printf(" -x, --xml\t\tUse XML output\n"); +@@ -76,19 +76,18 @@ static void print_usage(int argc, char **argv) + static void parse_opts(int argc, char **argv) + { + static struct option longopts[] = { +- {"help", 0, NULL, 'h'}, +- {"udid", 0, NULL, 'u'}, +- {"list", 0, NULL, 'l'}, +- {"imagetype", 0, NULL, 't'}, +- {"xml", 0, NULL, 'x'}, +- {"debug", 0, NULL, 'd'}, ++ {"help", no_argument, NULL, 'h'}, ++ {"udid", required_argument, NULL, 'u'}, ++ {"list", no_argument, NULL, 'l'}, ++ {"imagetype", required_argument, NULL, 't'}, ++ {"xml", no_argument, NULL, 'x'}, ++ {"debug", no_argument, NULL, 'd'}, + {NULL, 0, NULL, 0} + }; + int c; + + while (1) { +- c = getopt_long(argc, argv, "hu:lt:xd", longopts, +- (int *) 0); ++ c = getopt_long(argc, argv, "hu:lt:xd", longopts, NULL); + if (c == -1) { + break; + } +@@ -98,14 +97,12 @@ static void parse_opts(int argc, char **argv) + print_usage(argc, argv); + exit(0); + case 'u': +- if (strlen(optarg) != 40) { +- printf("%s: invalid UDID specified (length != 40)\n", +- argv[0]); ++ if (!*optarg) { ++ fprintf(stderr, "ERROR: UDID must not be empty!\n"); + print_usage(argc, argv); + exit(2); + } +- if (udid) +- free(udid); ++ free(udid); + udid = strdup(optarg); + break; + case 'l': +diff --git a/tools/ideviceinfo.c b/tools/ideviceinfo.c +index 40bcac6..59fade8 100644 +--- a/tools/ideviceinfo.c ++++ b/tools/ideviceinfo.c +@@ -91,7 +91,7 @@ static void print_usage(int argc, char **argv) + printf("Show information about a connected device.\n\n"); + printf(" -d, --debug\t\tenable communication debugging\n"); + printf(" -s, --simple\t\tuse a simple connection to avoid auto-pairing with the device\n"); +- printf(" -u, --udid UDID\ttarget specific device by its 40-digit device UDID\n"); ++ printf(" -u, --udid UDID\ttarget specific device by UDID\n"); + printf(" -q, --domain NAME\tset domain of query to NAME. Default: None\n"); + printf(" -k, --key NAME\tonly query key specified by NAME. Default: All keys.\n"); + printf(" -x, --xml\t\toutput information as xml plist instead of key/value pairs\n"); +@@ -129,7 +129,7 @@ int main(int argc, char *argv[]) + } + else if (!strcmp(argv[i], "-u") || !strcmp(argv[i], "--udid")) { + i++; +- if (!argv[i] || (strlen(argv[i]) != 40)) { ++ if (!argv[i] || !*argv[i]) { + print_usage(argc, argv); + return 0; + } +diff --git a/tools/idevicename.c b/tools/idevicename.c +index 013becc..ef226f7 100644 +--- a/tools/idevicename.c ++++ b/tools/idevicename.c +@@ -38,7 +38,7 @@ static void print_usage(void) + printf("Display the device name or set it to NAME if specified.\n"); + printf("\n"); + printf(" -d, --debug\t\tenable communication debugging\n"); +- printf(" -u, --udid UDID\tuse UDID to target a specific device\n"); ++ printf(" -u, --udid UDID\ttarget specific device by UDID\n"); + printf(" -h, --help\t\tprint usage information\n"); + printf("\n"); + printf("Homepage: <" PACKAGE_URL ">\n"); +@@ -60,6 +60,12 @@ int main(int argc, char** argv) + while ((c = getopt_long(argc, argv, "du:h", longopts, &optidx)) != -1) { + switch (c) { + case 'u': ++ if (!*optarg) { ++ fprintf(stderr, "ERROR: UDID must not be empty!\n"); ++ print_usage(); ++ exit(2); ++ } ++ free(udid); + udid = strdup(optarg); + break; + case 'h': +diff --git a/tools/idevicenotificationproxy.c b/tools/idevicenotificationproxy.c +index 5e4ac9a..72b406c 100644 +--- a/tools/idevicenotificationproxy.c ++++ b/tools/idevicenotificationproxy.c +@@ -70,7 +70,7 @@ static void print_usage(int argc, char **argv) + printf("\n"); + printf(" The following OPTIONS are accepted:\n"); + printf(" -d, --debug\t\tenable communication debugging\n"); +- printf(" -u, --udid UDID\ttarget specific device by its 40-digit device UDID\n"); ++ printf(" -u, --udid UDID\ttarget specific device by UDID\n"); + printf(" -h, --help\t\tprints usage information\n"); + printf("\n"); + printf("Homepage: <" PACKAGE_URL ">\n"); +@@ -114,7 +114,7 @@ int main(int argc, char *argv[]) + } + else if (!strcmp(argv[i], "-u") || !strcmp(argv[i], "--udid")) { + i++; +- if (!argv[i] || (strlen(argv[i]) != 40)) { ++ if (!argv[i] || !*argv[i]) { + print_usage(argc, argv); + result = 0; + goto cleanup; +diff --git a/tools/idevicepair.c b/tools/idevicepair.c +index b6f0751..6ae9103 100644 +--- a/tools/idevicepair.c ++++ b/tools/idevicepair.c +@@ -72,7 +72,7 @@ static void print_usage(int argc, char **argv) + printf(" list list devices paired with this host\n\n"); + printf(" The following OPTIONS are accepted:\n"); + printf(" -d, --debug enable communication debugging\n"); +- printf(" -u, --udid UDID target specific device by its 40-digit device UDID\n"); ++ printf(" -u, --udid UDID target specific device by UDID\n"); + printf(" -h, --help prints usage information\n"); + printf("\n"); + printf("Homepage: <" PACKAGE_URL ">\n"); +@@ -81,9 +81,9 @@ static void print_usage(int argc, char **argv) + static void parse_opts(int argc, char **argv) + { + static struct option longopts[] = { +- {"help", 0, NULL, 'h'}, +- {"udid", 1, NULL, 'u'}, +- {"debug", 0, NULL, 'd'}, ++ {"help", no_argument, NULL, 'h'}, ++ {"udid", required_argument, NULL, 'u'}, ++ {"debug", no_argument, NULL, 'd'}, + {NULL, 0, NULL, 0} + }; + int c; +@@ -99,8 +99,8 @@ static void parse_opts(int argc, char **argv) + print_usage(argc, argv); + exit(EXIT_SUCCESS); + case 'u': +- if (strlen(optarg) != 40) { +- printf("%s: invalid UDID specified (length != 40)\n", argv[0]); ++ if (!*optarg) { ++ fprintf(stderr, "ERROR: UDID must not be empty!\n"); + print_usage(argc, argv); + exit(2); + } +diff --git a/tools/ideviceprovision.c b/tools/ideviceprovision.c +index 0bef7e8..f91ce4f 100644 +--- a/tools/ideviceprovision.c ++++ b/tools/ideviceprovision.c +@@ -64,7 +64,7 @@ static void print_usage(int argc, char **argv) + printf(" \tspecified by FILE.\n\n"); + printf(" The following OPTIONS are accepted:\n"); + printf(" -d, --debug enable communication debugging\n"); +- printf(" -u, --udid UDID target specific device by its 40-digit device UDID\n"); ++ printf(" -u, --udid UDID target specific device by UDID\n"); + printf(" -x, --xml print XML output when using the 'dump' command\n"); + printf(" -h, --help prints usage information\n"); + printf("\n"); +@@ -299,7 +299,7 @@ int main(int argc, char *argv[]) + } + else if (!strcmp(argv[i], "-u") || !strcmp(argv[i], "--udid")) { + i++; +- if (!argv[i] || (strlen(argv[i]) != 40)) { ++ if (!argv[i] || !*argv[i]) { + print_usage(argc, argv); + return 0; + } +diff --git a/tools/idevicescreenshot.c b/tools/idevicescreenshot.c +index 74acdf6..f2bcd48 100644 +--- a/tools/idevicescreenshot.c ++++ b/tools/idevicescreenshot.c +@@ -55,7 +55,7 @@ int main(int argc, char **argv) + } + else if (!strcmp(argv[i], "-u") || !strcmp(argv[i], "--udid")) { + i++; +- if (!argv[i] || (strlen(argv[i]) != 40)) { ++ if (!argv[i] || !*argv[i]) { + print_usage(argc, argv); + return 0; + } +@@ -158,7 +158,7 @@ void print_usage(int argc, char **argv) + printf("NOTE: A mounted developer disk image is required on the device, otherwise\n"); + printf("the screenshotr service is not available.\n\n"); + printf(" -d, --debug\t\tenable communication debugging\n"); +- printf(" -u, --udid UDID\ttarget specific device by its 40-digit device UDID\n"); ++ printf(" -u, --udid UDID\ttarget specific device by UDID\n"); + printf(" -h, --help\t\tprints usage information\n"); + printf("\n"); + printf("Homepage: <" PACKAGE_URL ">\n"); +diff --git a/tools/idevicesyslog.c b/tools/idevicesyslog.c +index 0a923b8..76de128 100644 +--- a/tools/idevicesyslog.c ++++ b/tools/idevicesyslog.c +@@ -185,7 +185,7 @@ int main(int argc, char *argv[]) + } + else if (!strcmp(argv[i], "-u") || !strcmp(argv[i], "--udid")) { + i++; +- if (!argv[i] || (strlen(argv[i]) != 40)) { ++ if (!argv[i] || !*argv[i]) { + print_usage(argc, argv); + return 0; + } +@@ -238,7 +238,7 @@ void print_usage(int argc, char **argv) + printf("Usage: %s [OPTIONS]\n", (name ? name + 1: argv[0])); + printf("Relay syslog of a connected device.\n\n"); + printf(" -d, --debug\t\tenable communication debugging\n"); +- printf(" -u, --udid UDID\ttarget specific device by its 40-digit device UDID\n"); ++ printf(" -u, --udid UDID\ttarget specific device by UDID\n"); + printf(" -h, --help\t\tprints usage information\n"); + printf("\n"); + printf("Homepage: <" PACKAGE_URL ">\n"); +-- +2.23.0 + + +From d72b747e590044f9970ef26827f3af3ea9c1eb4a Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Mon, 29 Oct 2018 07:09:08 +0100 +Subject: [PATCH 086/151] idevicebackup2: Fix rmdir_recursive() not deleting + all files/directories (esp. on network filesystems) + +--- + tools/idevicebackup2.c | 75 +++++++++++++++++++++++++++++++----------- + 1 file changed, 55 insertions(+), 20 deletions(-) + +diff --git a/tools/idevicebackup2.c b/tools/idevicebackup2.c +index 6d4785b..02611a1 100644 +--- a/tools/idevicebackup2.c ++++ b/tools/idevicebackup2.c +@@ -2,8 +2,8 @@ + * idevicebackup2.c + * Command line interface to use the device's backup and restore service + * ++ * Copyright (c) 2010-2018 Nikias Bassen All Rights Reserved. + * Copyright (c) 2009-2010 Martin Szulecki All Rights Reserved. +- * Copyright (c) 2010 Nikias Bassen All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public +@@ -238,7 +238,12 @@ static int remove_directory(const char* path) + return e; + } + +-static int rmdir_recursive(const char* path) ++struct entry { ++ char *name; ++ struct entry *next; ++}; ++ ++static void scan_directory(const char *path, struct entry **files, struct entry **directories) + { + DIR* cur_dir = opendir(path); + if (cur_dir) { +@@ -249,31 +254,61 @@ static int rmdir_recursive(const char* path) + } + char *fpath = string_build_path(path, ep->d_name, NULL); + if (fpath) { +- struct stat st; +- if (stat(fpath, &st) == 0) { +- int res = 0; +- if (S_ISDIR(st.st_mode)) { +- res = rmdir_recursive(fpath); +- } else { +- res = remove_file(fpath); +- } +- if (res != 0) { +- free(fpath); +- closedir(cur_dir); +- return res; +- } ++ if (ep->d_type & DT_DIR) { ++ struct entry *ent = malloc(sizeof(struct entry)); ++ if (!ent) return; ++ ent->name = fpath; ++ ent->next = *directories; ++ *directories = ent; ++ scan_directory(fpath, files, directories); ++ fpath = NULL; + } else { +- free(fpath); +- closedir(cur_dir); +- return errno; ++ struct entry *ent = malloc(sizeof(struct entry)); ++ if (!ent) return; ++ ent->name = fpath; ++ ent->next = *files; ++ *files = ent; ++ fpath = NULL; + } + } +- free(fpath); + } + closedir(cur_dir); + } ++} ++ ++static int rmdir_recursive(const char* path) ++{ ++ int res = 0; ++ struct entry *files = NULL; ++ struct entry *directories = NULL; ++ struct entry *ent; ++ ++ ent = malloc(sizeof(struct entry)); ++ if (!ent) return ENOMEM; ++ ent->name = strdup(path); ++ ent->next = NULL; ++ directories = ent; ++ ++ scan_directory(path, &files, &directories); ++ ++ ent = files; ++ while (ent) { ++ struct entry *del = ent; ++ res = remove_file(ent->name); ++ free(ent->name); ++ ent = ent->next; ++ free(del); ++ } ++ ent = directories; ++ while (ent) { ++ struct entry *del = ent; ++ res = remove_directory(ent->name); ++ free(ent->name); ++ ent = ent->next; ++ free(del); ++ } + +- return remove_directory(path); ++ return res; + } + + static char* get_uuid() +-- +2.23.0 + + +From 92c5462adef87b1e577b8557b6b9c64d5a089544 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Tue, 30 Oct 2018 13:12:34 +0800 +Subject: [PATCH 087/151] idevicebackup2: Fix scan_directory() for platforms + not having d_type in struct dirent + +--- + configure.ac | 2 ++ + tools/idevicebackup2.c | 6 ++++++ + 2 files changed, 8 insertions(+) + +diff --git a/configure.ac b/configure.ac +index ec210fc..69ff13b 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -83,6 +83,8 @@ case ${host_os} in + esac + AM_CONDITIONAL(WIN32, test x$win32 = xtrue) + ++AC_CHECK_MEMBER(struct dirent.d_type, AC_DEFINE(HAVE_DIRENT_D_TYPE, 1, [define if struct dirent has member d_type]),, [#include ]) ++ + # Cython Python Bindings + AC_ARG_WITH([cython], + [AS_HELP_STRING([--without-cython], +diff --git a/tools/idevicebackup2.c b/tools/idevicebackup2.c +index 02611a1..f7ea53a 100644 +--- a/tools/idevicebackup2.c ++++ b/tools/idevicebackup2.c +@@ -254,7 +254,13 @@ static void scan_directory(const char *path, struct entry **files, struct entry + } + char *fpath = string_build_path(path, ep->d_name, NULL); + if (fpath) { ++#ifdef HAVE_DIRENT_D_TYPE + if (ep->d_type & DT_DIR) { ++#else ++ struct stat st; ++ if (stat(fpath, &st) != 0) return; ++ if (S_ISDIR(st.st_mode)) { ++#endif + struct entry *ent = malloc(sizeof(struct entry)); + if (!ent) return; + ent->name = fpath; +-- +2.23.0 + + +From 7e0eef5b4a6b43ee9534f6e6c60cddeefbf5c8a0 Mon Sep 17 00:00:00 2001 +From: Samuel Sadok +Date: Sat, 26 Jan 2019 12:45:24 +0100 +Subject: [PATCH 088/151] idevicebackup2: Write + /iTunesRestore/RestoreApplications.plist on restore + +This will trigger re-installation of apps that were installed when the backup +was created once the device finishes the restore and rebooted. +--- + tools/idevicebackup2.c | 65 ++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 62 insertions(+), 3 deletions(-) + +diff --git a/tools/idevicebackup2.c b/tools/idevicebackup2.c +index f7ea53a..e10846d 100644 +--- a/tools/idevicebackup2.c ++++ b/tools/idevicebackup2.c +@@ -1393,6 +1393,10 @@ int main(int argc, char *argv[]) + plist_t info_plist = NULL; + plist_t opts = NULL; + mobilebackup2_error_t err; ++ uint64_t restore_applications_file = 0; ++ plist_t applications_plist = NULL; ++ char * applications_plist_xml = NULL; ++ uint32_t applications_plist_xml_length = 0; + + /* we need to exit cleanly on running backups and restores or we cause havok */ + signal(SIGINT, clean_exit); +@@ -1709,7 +1713,7 @@ int main(int argc, char *argv[]) + } + + afc_client_t afc = NULL; +- if (cmd == CMD_BACKUP) { ++ if (cmd == CMD_BACKUP || cmd == CMD_RESTORE) { + /* start AFC, we need this for the lock file */ + service->port = 0; + service->ssl_enabled = 0; +@@ -1776,7 +1780,7 @@ int main(int argc, char *argv[]) + } + + uint64_t lockfile = 0; +- if (cmd == CMD_BACKUP) { ++ if (cmd == CMD_BACKUP || cmd == CMD_RESTORE) { + do_post_notification(device, NP_SYNC_WILL_START); + afc_file_open(afc, "/com.apple.itunes.lock_sync", AFC_FOPEN_RW, &lockfile); + } +@@ -1923,6 +1927,51 @@ checkpoint: + } + PRINT_VERBOSE(1, "Backup password: %s\n", (backup_password == NULL ? "No":"Yes")); + ++ /* Write /iTunesRestore/RestoreApplications.plist so that the device will start ++ * restoring applications once the rest of the restore process is finished */ ++ applications_plist = plist_dict_get_item(info_plist, "Applications"); ++ if (applications_plist) { ++ plist_to_xml(applications_plist, &applications_plist_xml, &applications_plist_xml_length); ++ plist_free(applications_plist); ++ } ++ if (!applications_plist_xml) { ++ printf("Error preparing RestoreApplications.plist\n"); ++ cmd = CMD_LEAVE; ++ break; ++ } ++ ++ afc_error_t afc_err = 0; ++ afc_err = afc_make_directory(afc, "/iTunesRestore"); ++ if (afc_err != AFC_E_SUCCESS) { ++ printf("Error creating directory /iTunesRestore, error code %d\n", afc_err); ++ cmd = CMD_LEAVE; ++ break; ++ } ++ ++ afc_err = afc_file_open(afc, "/iTunesRestore/RestoreApplications.plist", AFC_FOPEN_WR, &restore_applications_file); ++ if (afc_err != AFC_E_SUCCESS || !restore_applications_file) { ++ printf("Error creating /iTunesRestore/RestoreApplications.plist, error code %d\n", afc_err); ++ cmd = CMD_LEAVE; ++ break; ++ } ++ ++ uint32_t bytes_written = 0; ++ afc_err = afc_file_write(afc, restore_applications_file, applications_plist_xml, applications_plist_xml_length, &bytes_written); ++ if (afc_err != AFC_E_SUCCESS || bytes_written != applications_plist_xml_length) { ++ printf("Error writing /iTunesRestore/RestoreApplications.plist, error code %d, wrote %u of %u bytes\n", afc_err, bytes_written, applications_plist_xml_length); ++ cmd = CMD_LEAVE; ++ break; ++ } ++ ++ afc_err = afc_file_close(afc, restore_applications_file); ++ restore_applications_file = 0; ++ if (afc_err != AFC_E_SUCCESS) { ++ cmd = CMD_LEAVE; ++ break; ++ } ++ printf("Wrote RestoreApplications.plist\n"); ++ ++ /* Start restore */ + err = mobilebackup2_send_request(mobilebackup2, "Restore", udid, source_udid, opts); + plist_free(opts); + if (err != MOBILEBACKUP2_E_SUCCESS) { +@@ -2392,7 +2441,7 @@ files_out: + afc_file_lock(afc, lockfile, AFC_LOCK_UN); + afc_file_close(afc, lockfile); + lockfile = 0; +- if (cmd == CMD_BACKUP) ++ if (cmd == CMD_BACKUP || cmd == CMD_RESTORE) + do_post_notification(device, NP_SYNC_DID_FINISH); + } + } else { +@@ -2411,6 +2460,11 @@ files_out: + mobilebackup2 = NULL; + } + ++ if (restore_applications_file) { ++ afc_file_close(afc, restore_applications_file); ++ restore_applications_file = 0; ++ } ++ + if (afc) { + afc_client_free(afc); + afc = NULL; +@@ -2421,6 +2475,11 @@ files_out: + np = NULL; + } + ++ if (applications_plist_xml) { ++ free(applications_plist_xml); ++ applications_plist_xml = NULL; ++ } ++ + idevice_free(device); + device = NULL; + +-- +2.23.0 + + +From 67e3373d2e4bd55795e62b2d51ab99aeddf2406c Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Sat, 26 Jan 2019 13:07:08 +0100 +Subject: [PATCH 089/151] idevicebackup2: Move writing of + RestoreApplications.plist to helper function, add command line switch to skip + +--- + tools/idevicebackup2.c | 129 +++++++++++++++++++++++------------------ + 1 file changed, 72 insertions(+), 57 deletions(-) + +diff --git a/tools/idevicebackup2.c b/tools/idevicebackup2.c +index e10846d..c9eb9cb 100644 +--- a/tools/idevicebackup2.c ++++ b/tools/idevicebackup2.c +@@ -91,7 +91,8 @@ enum cmd_flags { + CMD_FLAG_ENCRYPTION_CHANGEPW = (1 << 8), + CMD_FLAG_FORCE_FULL_BACKUP = (1 << 9), + CMD_FLAG_CLOUD_ENABLE = (1 << 10), +- CMD_FLAG_CLOUD_DISABLE = (1 << 11) ++ CMD_FLAG_CLOUD_DISABLE = (1 << 11), ++ CMD_FLAG_RESTORE_SKIP_APPS = (1 << 12) + }; + + static int backup_domain_changed = 0; +@@ -536,6 +537,61 @@ static plist_t mobilebackup_factory_info_plist_new(const char* udid, idevice_t d + return ret; + } + ++static int write_restore_applications(plist_t info_plist, afc_client_t afc) ++{ ++ int res = -1; ++ uint64_t restore_applications_file = 0; ++ char * applications_plist_xml = NULL; ++ uint32_t applications_plist_xml_length = 0; ++ ++ plist_t applications_plist = plist_dict_get_item(info_plist, "Applications"); ++ if (applications_plist) { ++ plist_to_xml(applications_plist, &applications_plist_xml, &applications_plist_xml_length); ++ } ++ if (!applications_plist_xml) { ++ printf("Error preparing RestoreApplications.plist\n"); ++ goto leave; ++ } ++ ++ afc_error_t afc_err = 0; ++ afc_err = afc_make_directory(afc, "/iTunesRestore"); ++ if (afc_err != AFC_E_SUCCESS) { ++ printf("Error creating directory /iTunesRestore, error code %d\n", afc_err); ++ goto leave; ++ } ++ ++ afc_err = afc_file_open(afc, "/iTunesRestore/RestoreApplications.plist", AFC_FOPEN_WR, &restore_applications_file); ++ if (afc_err != AFC_E_SUCCESS || !restore_applications_file) { ++ printf("Error creating /iTunesRestore/RestoreApplications.plist, error code %d\n", afc_err); ++ goto leave; ++ } ++ ++ uint32_t bytes_written = 0; ++ afc_err = afc_file_write(afc, restore_applications_file, applications_plist_xml, applications_plist_xml_length, &bytes_written); ++ if (afc_err != AFC_E_SUCCESS || bytes_written != applications_plist_xml_length) { ++ printf("Error writing /iTunesRestore/RestoreApplications.plist, error code %d, wrote %u of %u bytes\n", afc_err, bytes_written, applications_plist_xml_length); ++ goto leave; ++ } ++ ++ afc_err = afc_file_close(afc, restore_applications_file); ++ restore_applications_file = 0; ++ if (afc_err != AFC_E_SUCCESS) { ++ goto leave; ++ } ++ /* success */ ++ res = 0; ++ ++leave: ++ free(applications_plist_xml); ++ ++ if (restore_applications_file) { ++ afc_file_close(afc, restore_applications_file); ++ restore_applications_file = 0; ++ } ++ ++ return res; ++} ++ + static int mb2_status_check_snapshot_state(const char *path, const char *udid, const char *matches) + { + int ret = 0; +@@ -1352,6 +1408,7 @@ static void print_usage(int argc, char **argv) + printf(" --copy\t\tcreate a copy of backup folder before restoring.\n"); + printf(" --settings\t\trestore device settings from the backup.\n"); + printf(" --remove\t\tremove items which are not being restored\n"); ++ printf(" --skip-apps\t\tdo not trigger re-installation of apps after restore\n"); + printf(" --password PWD\tsupply the password of the source backup\n"); + printf(" info\t\tshow details about last completed backup of device\n"); + printf(" list\t\tlist files of last completed backup in CSV format\n"); +@@ -1393,10 +1450,6 @@ int main(int argc, char *argv[]) + plist_t info_plist = NULL; + plist_t opts = NULL; + mobilebackup2_error_t err; +- uint64_t restore_applications_file = 0; +- plist_t applications_plist = NULL; +- char * applications_plist_xml = NULL; +- uint32_t applications_plist_xml_length = 0; + + /* we need to exit cleanly on running backups and restores or we cause havok */ + signal(SIGINT, clean_exit); +@@ -1459,6 +1512,9 @@ int main(int argc, char *argv[]) + else if (!strcmp(argv[i], "--remove")) { + cmd_flags |= CMD_FLAG_RESTORE_REMOVE_ITEMS; + } ++ else if (!strcmp(argv[i], "--skip-apps")) { ++ cmd_flags |= CMD_FLAG_RESTORE_SKIP_APPS; ++ } + else if (!strcmp(argv[i], "--password")) { + i++; + if (!argv[i]) { +@@ -1927,49 +1983,18 @@ checkpoint: + } + PRINT_VERBOSE(1, "Backup password: %s\n", (backup_password == NULL ? "No":"Yes")); + +- /* Write /iTunesRestore/RestoreApplications.plist so that the device will start +- * restoring applications once the rest of the restore process is finished */ +- applications_plist = plist_dict_get_item(info_plist, "Applications"); +- if (applications_plist) { +- plist_to_xml(applications_plist, &applications_plist_xml, &applications_plist_xml_length); +- plist_free(applications_plist); +- } +- if (!applications_plist_xml) { +- printf("Error preparing RestoreApplications.plist\n"); +- cmd = CMD_LEAVE; +- break; +- } +- +- afc_error_t afc_err = 0; +- afc_err = afc_make_directory(afc, "/iTunesRestore"); +- if (afc_err != AFC_E_SUCCESS) { +- printf("Error creating directory /iTunesRestore, error code %d\n", afc_err); +- cmd = CMD_LEAVE; +- break; +- } +- +- afc_err = afc_file_open(afc, "/iTunesRestore/RestoreApplications.plist", AFC_FOPEN_WR, &restore_applications_file); +- if (afc_err != AFC_E_SUCCESS || !restore_applications_file) { +- printf("Error creating /iTunesRestore/RestoreApplications.plist, error code %d\n", afc_err); +- cmd = CMD_LEAVE; +- break; +- } +- +- uint32_t bytes_written = 0; +- afc_err = afc_file_write(afc, restore_applications_file, applications_plist_xml, applications_plist_xml_length, &bytes_written); +- if (afc_err != AFC_E_SUCCESS || bytes_written != applications_plist_xml_length) { +- printf("Error writing /iTunesRestore/RestoreApplications.plist, error code %d, wrote %u of %u bytes\n", afc_err, bytes_written, applications_plist_xml_length); +- cmd = CMD_LEAVE; +- break; +- } +- +- afc_err = afc_file_close(afc, restore_applications_file); +- restore_applications_file = 0; +- if (afc_err != AFC_E_SUCCESS) { +- cmd = CMD_LEAVE; +- break; ++ if (cmd_flags & CMD_FLAG_RESTORE_SKIP_APPS) { ++ PRINT_VERBOSE(1, "Not writing RestoreApplications.plist - apps will not be re-installed after restore\n"); ++ } else { ++ /* Write /iTunesRestore/RestoreApplications.plist so that the device will start ++ * restoring applications once the rest of the restore process is finished */ ++ if (write_restore_applications(info_plist, afc) < 0) { ++ cmd = CMD_LEAVE; ++ break; ++ } else { ++ PRINT_VERBOSE(1, "Wrote RestoreApplications.plist\n"); ++ } + } +- printf("Wrote RestoreApplications.plist\n"); + + /* Start restore */ + err = mobilebackup2_send_request(mobilebackup2, "Restore", udid, source_udid, opts); +@@ -2460,11 +2485,6 @@ files_out: + mobilebackup2 = NULL; + } + +- if (restore_applications_file) { +- afc_file_close(afc, restore_applications_file); +- restore_applications_file = 0; +- } +- + if (afc) { + afc_client_free(afc); + afc = NULL; +@@ -2475,11 +2495,6 @@ files_out: + np = NULL; + } + +- if (applications_plist_xml) { +- free(applications_plist_xml); +- applications_plist_xml = NULL; +- } +- + idevice_free(device); + device = NULL; + +-- +2.23.0 + + +From d200973897e281ba35d6c9c433e1355a49056da8 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Sat, 26 Jan 2019 13:32:48 +0100 +Subject: [PATCH 090/151] idevicebackup2: Make reboot after restore the default + +As seen in #726 the previous behavior results in wrong assumptions that a +restore is possible without rebooting the device, however this is not how +iOS is handling it. +I added a command line switch --no-reboot now that will let you still +restore without rebooting, if anyone wants to play around with that... +--- + tools/idevicebackup2.c | 15 +++++++++------ + 1 file changed, 9 insertions(+), 6 deletions(-) + +diff --git a/tools/idevicebackup2.c b/tools/idevicebackup2.c +index c9eb9cb..1e6ddf7 100644 +--- a/tools/idevicebackup2.c ++++ b/tools/idevicebackup2.c +@@ -82,7 +82,7 @@ enum cmd_mode { + + enum cmd_flags { + CMD_FLAG_RESTORE_SYSTEM_FILES = (1 << 1), +- CMD_FLAG_RESTORE_REBOOT = (1 << 2), ++ CMD_FLAG_RESTORE_NO_REBOOT = (1 << 2), + CMD_FLAG_RESTORE_COPY_BACKUP = (1 << 3), + CMD_FLAG_RESTORE_SETTINGS = (1 << 4), + CMD_FLAG_RESTORE_REMOVE_ITEMS = (1 << 5), +@@ -1404,7 +1404,7 @@ static void print_usage(int argc, char **argv) + printf(" --full\t\tforce full backup from device.\n"); + printf(" restore\trestore last backup to the device\n"); + printf(" --system\t\trestore system files, too.\n"); +- printf(" --reboot\t\treboot the system when done.\n"); ++ printf(" --no-reboot\t\tdo NOT reboot the system when done (default: yes).\n"); + printf(" --copy\t\tcreate a copy of backup folder before restoring.\n"); + printf(" --settings\t\trestore device settings from the backup.\n"); + printf(" --remove\t\tremove items which are not being restored\n"); +@@ -1501,7 +1501,10 @@ int main(int argc, char *argv[]) + cmd_flags |= CMD_FLAG_RESTORE_SYSTEM_FILES; + } + else if (!strcmp(argv[i], "--reboot")) { +- cmd_flags |= CMD_FLAG_RESTORE_REBOOT; ++ cmd_flags &= ~CMD_FLAG_RESTORE_NO_REBOOT; ++ } ++ else if (!strcmp(argv[i], "--no-reboot")) { ++ cmd_flags |= CMD_FLAG_RESTORE_NO_REBOOT; + } + else if (!strcmp(argv[i], "--copy")) { + cmd_flags |= CMD_FLAG_RESTORE_COPY_BACKUP; +@@ -1967,9 +1970,9 @@ checkpoint: + opts = plist_new_dict(); + plist_dict_set_item(opts, "RestoreSystemFiles", plist_new_bool(cmd_flags & CMD_FLAG_RESTORE_SYSTEM_FILES)); + PRINT_VERBOSE(1, "Restoring system files: %s\n", (cmd_flags & CMD_FLAG_RESTORE_SYSTEM_FILES ? "Yes":"No")); +- if ((cmd_flags & CMD_FLAG_RESTORE_REBOOT) == 0) ++ if (cmd_flags & CMD_FLAG_RESTORE_NO_REBOOT) + plist_dict_set_item(opts, "RestoreShouldReboot", plist_new_bool(0)); +- PRINT_VERBOSE(1, "Rebooting after restore: %s\n", (cmd_flags & CMD_FLAG_RESTORE_REBOOT ? "Yes":"No")); ++ PRINT_VERBOSE(1, "Rebooting after restore: %s\n", (cmd_flags & CMD_FLAG_RESTORE_NO_REBOOT ? "No":"Yes")); + if ((cmd_flags & CMD_FLAG_RESTORE_COPY_BACKUP) == 0) + plist_dict_set_item(opts, "RestoreDontCopyBackup", plist_new_bool(1)); + PRINT_VERBOSE(1, "Don't copy backup: %s\n", ((cmd_flags & CMD_FLAG_RESTORE_COPY_BACKUP) == 0 ? "Yes":"No")); +@@ -2440,7 +2443,7 @@ files_out: + } + break; + case CMD_RESTORE: +- if (cmd_flags & CMD_FLAG_RESTORE_REBOOT) ++ if ((cmd_flags & CMD_FLAG_RESTORE_NO_REBOOT) == 0) + PRINT_VERBOSE(1, "The device should reboot now.\n"); + if (operation_ok) { + PRINT_VERBOSE(1, "Restore Successful.\n"); +-- +2.23.0 + + +From 8ef9e51d8514a441dc9b7d035954691d880a543e Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Fri, 8 Feb 2019 09:00:36 +0100 +Subject: [PATCH 091/151] idevicepair: Fix 'validate' command which was broken + since iOS 11 + +Apple removed the lockdownd command 'ValidatePair'. Validating a pairing +can just be done by trying to use the present pairing record to try to +start a lockdownd session: if it succeeds, the pairing is valid, otherwise +obviously not. So this is what we do now. +--- + tools/idevicepair.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/tools/idevicepair.c b/tools/idevicepair.c +index 6ae9103..0b866ea 100644 +--- a/tools/idevicepair.c ++++ b/tools/idevicepair.c +@@ -2,8 +2,8 @@ + * idevicepair.c + * Manage pairings with devices and this host + * +- * Copyright (c) 2014 Martin Szulecki All Rights Reserved. +- * Copyright (c) 2010 Nikias Bassen All Rights Reserved. ++ * Copyright (c) 2010-2019 Nikias Bassen, All Rights Reserved. ++ * Copyright (c) 2014 Martin Szulecki, All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public +@@ -266,7 +266,9 @@ int main(int argc, char **argv) + break; + + case OP_VALIDATE: +- lerr = lockdownd_validate_pair(client, NULL); ++ lockdownd_client_free(client); ++ client = NULL; ++ lerr = lockdownd_client_new_with_handshake(device, &client, "idevicepair"); + if (lerr == LOCKDOWN_E_SUCCESS) { + printf("SUCCESS: Validated pairing with device %s\n", udid); + } else { +-- +2.23.0 + + +From 797a9e7e79d86427f40dbb82d271125b8c0b2485 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Sat, 9 Feb 2019 03:14:50 +0100 +Subject: [PATCH 092/151] idevicepair: Add another error case instead of + printing 'unhandled error' + +--- + tools/idevicepair.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/tools/idevicepair.c b/tools/idevicepair.c +index 0b866ea..77c46b7 100644 +--- a/tools/idevicepair.c ++++ b/tools/idevicepair.c +@@ -41,6 +41,7 @@ static void print_error_message(lockdownd_error_t err) + case LOCKDOWN_E_PASSWORD_PROTECTED: + printf("ERROR: Could not validate with device %s because a passcode is set. Please enter the passcode on the device and retry.\n", udid); + break; ++ case LOCKDOWN_E_INVALID_CONF: + case LOCKDOWN_E_INVALID_HOST_ID: + printf("ERROR: Device %s is not paired with this host\n", udid); + break; +-- +2.23.0 + + +From cccc965ff1a87ac70d9fe4b10f8cad28c3de2874 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Tue, 12 Feb 2019 21:46:48 +0100 +Subject: [PATCH 093/151] lockdown: Make sure to return correct error code when + pairing fails + +--- + src/lockdown.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/lockdown.c b/src/lockdown.c +index 2492897..1a162ed 100644 +--- a/src/lockdown.c ++++ b/src/lockdown.c +@@ -726,7 +726,7 @@ LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_client_new_with_handshake(idevi + if (pair_record) { + pair_record_get_host_id(pair_record, &host_id); + } +- if (LOCKDOWN_E_SUCCESS == ret && !host_id) { ++ if (LOCKDOWN_E_SUCCESS == ret && pair_record && !host_id) { + ret = LOCKDOWN_E_INVALID_CONF; + } + +-- +2.23.0 + + +From 0584aa90c93ff6ce46927b8d67887cb987ab9545 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Sat, 16 Feb 2019 21:42:53 +0100 +Subject: [PATCH 094/151] idevicepair: Fix udid being freed before printing + error message containing udid + +--- + tools/idevicepair.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/tools/idevicepair.c b/tools/idevicepair.c +index 77c46b7..be1f373 100644 +--- a/tools/idevicepair.c ++++ b/tools/idevicepair.c +@@ -192,12 +192,13 @@ int main(int argc, char **argv) + + if (udid) { + ret = idevice_new(&device, udid); +- free(udid); +- udid = NULL; + if (ret != IDEVICE_E_SUCCESS) { + printf("No device found with udid %s, is it plugged in?\n", udid); ++ free(udid); + return EXIT_FAILURE; + } ++ free(udid); ++ udid = NULL; + } else { + ret = idevice_new(&device, NULL); + if (ret != IDEVICE_E_SUCCESS) { +-- +2.23.0 + + +From eea4f1be9107c8ab621fd71460e47d0d38e55d71 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Thu, 4 Apr 2019 01:54:18 +0300 +Subject: [PATCH 095/151] Updated ac_python_devel.m4 to newer + ax_python_devel.m4 + +--- + m4/{ac_python_devel.m4 => ax_python_devel.m4} | 188 ++++++++++++------ + 1 file changed, 123 insertions(+), 65 deletions(-) + rename m4/{ac_python_devel.m4 => ax_python_devel.m4} (61%) + +diff --git a/m4/ac_python_devel.m4 b/m4/ax_python_devel.m4 +similarity index 61% +rename from m4/ac_python_devel.m4 +rename to m4/ax_python_devel.m4 +index 545c607..44dbd83 100644 +--- a/m4/ac_python_devel.m4 ++++ b/m4/ax_python_devel.m4 +@@ -1,10 +1,10 @@ + # =========================================================================== +-# http://autoconf-archive.cryp.to/ac_python_devel.html ++# https://www.gnu.org/software/autoconf-archive/ax_python_devel.html + # =========================================================================== + # + # SYNOPSIS + # +-# AC_PYTHON_DEVEL([version]) ++# AX_PYTHON_DEVEL([version]) + # + # DESCRIPTION + # +@@ -12,8 +12,8 @@ + # in your configure.ac. + # + # This macro checks for Python and tries to get the include path to +-# 'Python.h'. It provides the $(PYTHON_CPPFLAGS) and $(PYTHON_LDFLAGS) +-# output variables. It also exports $(PYTHON_EXTRA_LIBS) and ++# 'Python.h'. It provides the $(PYTHON_CPPFLAGS) and $(PYTHON_LIBS) output ++# variables. It also exports $(PYTHON_EXTRA_LIBS) and + # $(PYTHON_EXTRA_LDFLAGS) for embedding Python in your code. + # + # You can search for some particular version of Python by passing a +@@ -31,18 +31,15 @@ + # If you need to use this macro for an older Python version, please + # contact the authors. We're always open for feedback. + # +-# LAST MODIFICATION ++# LICENSE + # +-# 2008-04-12 +-# +-# COPYLEFT +-# +-# Copyright (c) 2008 Sebastian Huber +-# Copyright (c) 2008 Alan W. Irwin +-# Copyright (c) 2008 Rafael Laboissiere +-# Copyright (c) 2008 Andrew Collier +-# Copyright (c) 2008 Matteo Settenvini +-# Copyright (c) 2008 Horst Knorr ++# Copyright (c) 2009 Sebastian Huber ++# Copyright (c) 2009 Alan W. Irwin ++# Copyright (c) 2009 Rafael Laboissiere ++# Copyright (c) 2009 Andrew Collier ++# Copyright (c) 2009 Matteo Settenvini ++# Copyright (c) 2009 Horst Knorr ++# Copyright (c) 2013 Daniel Mullner + # + # This program is free software: you can redistribute it and/or modify it + # under the terms of the GNU General Public License as published by the +@@ -55,7 +52,7 @@ + # Public License for more details. + # + # You should have received a copy of the GNU General Public License along +-# with this program. If not, see . ++# with this program. If not, see . + # + # As a special exception, the respective Autoconf Macro's copyright owner + # gives unlimited permission to copy, distribute and modify the configure +@@ -66,11 +63,14 @@ + # all other use of the material that constitutes the Autoconf Macro. + # + # This special exception to the GPL applies to versions of the Autoconf +-# Macro released by the Autoconf Macro Archive. When you make and +-# distribute a modified version of the Autoconf Macro, you may extend this +-# special exception to the GPL to apply to your modified version as well. ++# Macro released by the Autoconf Archive. When you make and distribute a ++# modified version of the Autoconf Macro, you may extend this special ++# exception to the GPL to apply to your modified version as well. + +-AC_DEFUN([AC_PYTHON_DEVEL],[ ++#serial 21 ++ ++AU_ALIAS([AC_PYTHON_DEVEL], [AX_PYTHON_DEVEL]) ++AC_DEFUN([AX_PYTHON_DEVEL],[ + # + # Allow the use of a (user set) custom python version + # +@@ -90,8 +90,8 @@ AC_DEFUN([AC_PYTHON_DEVEL],[ + # + AC_MSG_CHECKING([for a version of Python >= '2.1.0']) + ac_supports_python_ver=`$PYTHON -c "import sys; \ +- ver = sys.version.split()[[0]]; \ +- print(ver >= '2.1.0')"` ++ ver = sys.version.split ()[[0]]; \ ++ print (ver >= '2.1.0')"` + if test "$ac_supports_python_ver" != "True"; then + if test -z "$PYTHON_NOVERSIONCHECK"; then + AC_MSG_RESULT([no]) +@@ -99,7 +99,7 @@ AC_DEFUN([AC_PYTHON_DEVEL],[ + This version of the AC@&t@_PYTHON_DEVEL macro + doesn't work properly with versions of Python before + 2.1.0. You may need to re-run configure, setting the +-variables PYTHON_CPPFLAGS, PYTHON_LDFLAGS, PYTHON_SITE_PKG, ++variables PYTHON_CPPFLAGS, PYTHON_LIBS, PYTHON_SITE_PKG, + PYTHON_EXTRA_LIBS and PYTHON_EXTRA_LDFLAGS by hand. + Moreover, to disable this check, set PYTHON_NOVERSIONCHECK + to something else than an empty string. +@@ -117,10 +117,10 @@ to something else than an empty string. + if test -n "$1"; then + AC_MSG_CHECKING([for a version of Python $1]) + ac_supports_python_ver=`$PYTHON -c "import sys; \ +- ver = sys.version.split()[[0]]; \ +- print(ver >= '2.1.0')"` ++ ver = sys.version.split ()[[0]]; \ ++ print (ver $1)"` + if test "$ac_supports_python_ver" = "True"; then +- AC_MSG_RESULT([yes]) ++ AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + AC_MSG_ERROR([this package requires Python $1. +@@ -137,7 +137,7 @@ variable to configure. See ``configure --help'' for reference. + # + AC_MSG_CHECKING([for the distutils Python package]) + ac_distutils_result=`$PYTHON -c "import distutils" 2>&1` +- if test -z "$ac_distutils_result"; then ++ if test $? -eq 0; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) +@@ -151,14 +151,17 @@ $ac_distutils_result]) + # Check for Python include path + # + AC_MSG_CHECKING([for Python include path]) +- if type $PYTHON-config; then +- PYTHON_CPPFLAGS=`$PYTHON-config --includes` +- fi + if test -z "$PYTHON_CPPFLAGS"; then + python_path=`$PYTHON -c "import distutils.sysconfig; \ +- print(distutils.sysconfig.get_python_inc());"` ++ print (distutils.sysconfig.get_python_inc ());"` ++ plat_python_path=`$PYTHON -c "import distutils.sysconfig; \ ++ print (distutils.sysconfig.get_python_inc (plat_specific=1));"` + if test -n "${python_path}"; then +- python_path="-I$python_path" ++ if test "${plat_python_path}" != "${python_path}"; then ++ python_path="-I$python_path -I$plat_python_path" ++ else ++ python_path="-I$python_path" ++ fi + fi + PYTHON_CPPFLAGS=$python_path + fi +@@ -169,29 +172,80 @@ $ac_distutils_result]) + # Check for Python library path + # + AC_MSG_CHECKING([for Python library path]) +- if type $PYTHON-config; then +- PYTHON_LDFLAGS=`$PYTHON-config --ldflags` +- fi +- if test -z "$PYTHON_LDFLAGS"; then ++ if test -z "$PYTHON_LIBS"; then + # (makes two attempts to ensure we've got a version number + # from the interpreter) +- py_version=`$PYTHON -c "from distutils.sysconfig import *; \ +- print(' '.join(get_config_vars('VERSION')))"` +- if test "$py_version" = "[None]"; then ++ ac_python_version=`cat< +- ],[ +- Py_Initialize(); +- ],[pythonexists=yes],[pythonexists=no]) ++ AC_LANG_PUSH([C]) ++ AC_LINK_IFELSE([ ++ AC_LANG_PROGRAM([[#include ]], ++ [[Py_Initialize();]]) ++ ],[pythonexists=yes],[pythonexists=no]) ++ AC_LANG_POP([C]) ++ # turn back to default flags ++ CPPFLAGS="$ac_save_CPPFLAGS" ++ LIBS="$ac_save_LIBS" ++ LDFLAGS="$ac_save_LDFLAGS" + + AC_MSG_RESULT([$pythonexists]) + +- if test ! "$pythonexists" = "yes"; then +- AC_MSG_ERROR([ ++ if test ! "x$pythonexists" = "xyes"; then ++ AC_MSG_FAILURE([ + Could not link test program to Python. Maybe the main Python library has been + installed in some non-standard library path. If so, pass it to configure, +- via the LDFLAGS environment variable. +- Example: ./configure LDFLAGS="-L/usr/non-standard-path/python/lib" ++ via the LIBS environment variable. ++ Example: ./configure LIBS="-L/usr/non-standard-path/python/lib" + ============================================================================ + ERROR! + You probably have to install the development version of the Python package +@@ -258,10 +320,6 @@ $ac_distutils_result]) + ]) + PYTHON_VERSION="" + fi +- AC_LANG_POP +- # turn back to default flags +- CPPFLAGS="$ac_save_CPPFLAGS" +- LIBS="$ac_save_LIBS" + + # + # all done! +-- +2.23.0 + + +From 4727a86940875ab6f55cd0ddb7be99a705686f53 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Tue, 21 May 2019 02:55:06 +0200 +Subject: [PATCH 096/151] common: Update socket.c to match the one from + libusbmuxd + +--- + common/socket.c | 215 +++++++++++++++++++++++++++++++++++------------- + common/socket.h | 10 +-- + 2 files changed, 165 insertions(+), 60 deletions(-) + +diff --git a/common/socket.c b/common/socket.c +index e2968a6..aa97848 100644 +--- a/common/socket.c ++++ b/common/socket.c +@@ -1,8 +1,8 @@ + /* + * socket.c + * +- * Copyright (c) 2012 Martin Szulecki All Rights Reserved. +- * Copyright (c) 2012 Nikias Bassen All Rights Reserved. ++ * Copyright (C) 2012-2018 Nikias Bassen ++ * Copyright (C) 2012 Martin Szulecki + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public +@@ -19,6 +19,9 @@ + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + ++#ifdef HAVE_CONFIG_H ++#include ++#endif + #include + #include + #include +@@ -29,18 +32,26 @@ + #include + #ifdef WIN32 + #include ++#include + #include + static int wsa_init = 0; + #else + #include + #include + #include ++#include + #include + #include ++#include + #endif + #include "socket.h" + + #define RECV_TIMEOUT 20000 ++#define CONNECT_TIMEOUT 5000 ++ ++#ifndef ECONNRESET ++#define ECONNRESET 108 ++#endif + + static int verbose = 0; + +@@ -54,34 +65,34 @@ int socket_create_unix(const char *filename) + { + struct sockaddr_un name; + int sock; +- size_t size; ++#ifdef SO_NOSIGPIPE ++ int yes = 1; ++#endif + + // remove if still present + unlink(filename); + + /* Create the socket. */ +- sock = socket(PF_LOCAL, SOCK_STREAM, 0); ++ sock = socket(PF_UNIX, SOCK_STREAM, 0); + if (sock < 0) { + perror("socket"); + return -1; + } + ++#ifdef SO_NOSIGPIPE ++ if (setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, (void*)&yes, sizeof(int)) == -1) { ++ perror("setsockopt()"); ++ socket_close(sock); ++ return -1; ++ } ++#endif ++ + /* Bind a name to the socket. */ +- name.sun_family = AF_LOCAL; ++ name.sun_family = AF_UNIX; + strncpy(name.sun_path, filename, sizeof(name.sun_path)); + name.sun_path[sizeof(name.sun_path) - 1] = '\0'; + +- /* The size of the address is +- the offset of the start of the filename, +- plus its length, +- plus one for the terminating null byte. +- Alternatively you can just do: +- size = SUN_LEN (&name); +- */ +- size = (offsetof(struct sockaddr_un, sun_path) +- + strlen(name.sun_path) + 1); +- +- if (bind(sock, (struct sockaddr *) &name, size) < 0) { ++ if (bind(sock, (struct sockaddr*)&name, sizeof(name)) < 0) { + perror("bind"); + socket_close(sock); + return -1; +@@ -100,8 +111,11 @@ int socket_connect_unix(const char *filename) + { + struct sockaddr_un name; + int sfd = -1; +- size_t size; + struct stat fst; ++#ifdef SO_NOSIGPIPE ++ int yes = 1; ++#endif ++ int bufsize = 0x20000; + + // check if socket file exists... + if (stat(filename, &fst) != 0) { +@@ -118,20 +132,33 @@ int socket_connect_unix(const char *filename) + return -1; + } + // make a new socket +- if ((sfd = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0) { ++ if ((sfd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) { + if (verbose >= 2) + fprintf(stderr, "%s: socket: %s\n", __func__, strerror(errno)); + return -1; + } ++ ++ if (setsockopt(sfd, SOL_SOCKET, SO_SNDBUF, (void*)&bufsize, sizeof(int)) == -1) { ++ perror("Could not set send buffer for socket"); ++ } ++ ++ if (setsockopt(sfd, SOL_SOCKET, SO_RCVBUF, (void*)&bufsize, sizeof(int)) == -1) { ++ perror("Could not set receive buffer for socket"); ++ } ++ ++#ifdef SO_NOSIGPIPE ++ if (setsockopt(sfd, SOL_SOCKET, SO_NOSIGPIPE, (void*)&yes, sizeof(int)) == -1) { ++ perror("setsockopt()"); ++ socket_close(sfd); ++ return -1; ++ } ++#endif + // and connect to 'filename' +- name.sun_family = AF_LOCAL; ++ name.sun_family = AF_UNIX; + strncpy(name.sun_path, filename, sizeof(name.sun_path)); + name.sun_path[sizeof(name.sun_path) - 1] = 0; + +- size = (offsetof(struct sockaddr_un, sun_path) +- + strlen(name.sun_path) + 1); +- +- if (connect(sfd, (struct sockaddr *) &name, size) < 0) { ++ if (connect(sfd, (struct sockaddr*)&name, sizeof(name)) < 0) { + socket_close(sfd); + if (verbose >= 2) + fprintf(stderr, "%s: connect: %s\n", __func__, +@@ -170,6 +197,14 @@ int socket_create(uint16_t port) + return -1; + } + ++#ifdef SO_NOSIGPIPE ++ if (setsockopt(sfd, SOL_SOCKET, SO_NOSIGPIPE, (void*)&yes, sizeof(int)) == -1) { ++ perror("setsockopt()"); ++ socket_close(sfd); ++ return -1; ++ } ++#endif ++ + memset((void *) &saddr, 0, sizeof(saddr)); + saddr.sin_family = AF_INET; + saddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); +@@ -194,9 +229,14 @@ int socket_connect(const char *addr, uint16_t port) + { + int sfd = -1; + int yes = 1; +- struct hostent *hp; +- struct sockaddr_in saddr; ++ int bufsize = 0x20000; ++ struct addrinfo hints; ++ struct addrinfo *result, *rp; ++ char portstr[8]; ++ int res; + #ifdef WIN32 ++ u_long l_yes = 1; ++ u_long l_no = 0; + WSADATA wsa_data; + if (!wsa_init) { + if (WSAStartup(MAKEWORD(2,2), &wsa_data) != ERROR_SUCCESS) { +@@ -205,6 +245,8 @@ int socket_connect(const char *addr, uint16_t port) + } + wsa_init = 1; + } ++#else ++ int flags = 0; + #endif + + if (!addr) { +@@ -212,39 +254,99 @@ int socket_connect(const char *addr, uint16_t port) + return -1; + } + +- if ((hp = gethostbyname(addr)) == NULL) { +- if (verbose >= 2) +- fprintf(stderr, "%s: unknown host '%s'\n", __func__, addr); ++ memset(&hints, '\0', sizeof(struct addrinfo)); ++ hints.ai_family = AF_UNSPEC; ++ hints.ai_socktype = SOCK_STREAM; ++ hints.ai_flags = 0; ++ hints.ai_protocol = IPPROTO_TCP; ++ ++ sprintf(portstr, "%d", port); ++ ++ res = getaddrinfo(addr, portstr, &hints, &result); ++ if (res != 0) { ++ fprintf(stderr, "%s: getaddrinfo: %s\n", __func__, gai_strerror(res)); + return -1; + } + +- if (!hp->h_addr) { +- if (verbose >= 2) +- fprintf(stderr, "%s: gethostbyname returned NULL address!\n", +- __func__); +- return -1; ++ for (rp = result; rp != NULL; rp = rp->ai_next) { ++ sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); ++ if (sfd == -1) { ++ continue; ++ } ++ ++ if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (void*)&yes, sizeof(int)) == -1) { ++ perror("setsockopt()"); ++ socket_close(sfd); ++ continue; ++ } ++ ++#ifdef WIN32 ++ ioctlsocket(sfd, FIONBIO, &l_yes); ++#else ++ fcntl(sfd, F_SETFL, O_NONBLOCK); ++#endif ++ ++ if (connect(sfd, rp->ai_addr, rp->ai_addrlen) != -1) { ++ break; ++ } ++#ifdef WIN32 ++ if (WSAGetLastError() == WSAEWOULDBLOCK) ++#else ++ if (errno == EINPROGRESS) ++#endif ++ { ++ fd_set fds; ++ FD_ZERO(&fds); ++ FD_SET(sfd, &fds); ++ ++ struct timeval timeout; ++ timeout.tv_sec = CONNECT_TIMEOUT / 1000; ++ timeout.tv_usec = (CONNECT_TIMEOUT - (timeout.tv_sec * 1000)) * 1000; ++ if (select(sfd + 1, NULL, &fds, NULL, &timeout) == 1) { ++ int so_error; ++ socklen_t len = sizeof(so_error); ++ getsockopt(sfd, SOL_SOCKET, SO_ERROR, (void*)&so_error, &len); ++ if (so_error == 0) { ++ break; ++ } ++ } ++ } ++ socket_close(sfd); + } + +- if (0 > (sfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP))) { +- perror("socket()"); ++ freeaddrinfo(result); ++ ++ if (rp == NULL) { ++ if (verbose >= 2) ++ fprintf(stderr, "%s: Could not connect to %s:%d\n", __func__, addr, port); + return -1; + } + +- if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (void*)&yes, sizeof(int)) == -1) { ++#ifdef WIN32 ++ ioctlsocket(sfd, FIONBIO, &l_no); ++#else ++ flags = fcntl(sfd, F_GETFL, 0); ++ fcntl(sfd, F_SETFL, flags & (~O_NONBLOCK)); ++#endif ++ ++#ifdef SO_NOSIGPIPE ++ if (setsockopt(sfd, SOL_SOCKET, SO_NOSIGPIPE, (void*)&yes, sizeof(int)) == -1) { + perror("setsockopt()"); + socket_close(sfd); + return -1; + } ++#endif + +- memset((void *) &saddr, 0, sizeof(saddr)); +- saddr.sin_family = AF_INET; +- saddr.sin_addr.s_addr = *(uint32_t *) hp->h_addr; +- saddr.sin_port = htons(port); ++ if (setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, (void*)&yes, sizeof(int)) == -1) { ++ perror("Could not set TCP_NODELAY on socket"); ++ } + +- if (connect(sfd, (struct sockaddr *) &saddr, sizeof(saddr)) < 0) { +- perror("connect"); +- socket_close(sfd); +- return -2; ++ if (setsockopt(sfd, SOL_SOCKET, SO_SNDBUF, (void*)&bufsize, sizeof(int)) == -1) { ++ perror("Could not set send buffer for socket"); ++ } ++ ++ if (setsockopt(sfd, SOL_SOCKET, SO_RCVBUF, (void*)&bufsize, sizeof(int)) == -1) { ++ perror("Could not set receive buffer for socket"); + } + + return sfd; +@@ -258,7 +360,7 @@ int socket_check_fd(int fd, fd_mode fdm, unsigned int timeout) + struct timeval to; + struct timeval *pto; + +- if (fd <= 0) { ++ if (fd < 0) { + if (verbose >= 2) + fprintf(stderr, "ERROR: invalid fd in check_fd %d\n", fd); + return -1; +@@ -267,17 +369,16 @@ int socket_check_fd(int fd, fd_mode fdm, unsigned int timeout) + FD_ZERO(&fds); + FD_SET(fd, &fds); + +- if (timeout > 0) { +- to.tv_sec = (time_t) (timeout / 1000); +- to.tv_usec = (time_t) ((timeout - (to.tv_sec * 1000)) * 1000); +- pto = &to; +- } else { +- pto = NULL; +- } +- + sret = -1; + + do { ++ if (timeout > 0) { ++ to.tv_sec = (time_t) (timeout / 1000); ++ to.tv_usec = (time_t) ((timeout - (to.tv_sec * 1000)) * 1000); ++ pto = &to; ++ } else { ++ pto = NULL; ++ } + eagain = 0; + switch (fdm) { + case FDM_READ: +@@ -378,7 +479,7 @@ int socket_receive_timeout(int fd, void *data, size_t length, int flags, + // but this is an error condition + if (verbose >= 3) + fprintf(stderr, "%s: fd=%d recv returned 0\n", __func__, fd); +- return -EAGAIN; ++ return -ECONNRESET; + } + if (result < 0) { + return -errno; +@@ -388,5 +489,9 @@ int socket_receive_timeout(int fd, void *data, size_t length, int flags, + + int socket_send(int fd, void *data, size_t length) + { +- return send(fd, data, length, 0); ++ int flags = 0; ++#ifdef MSG_NOSIGNAL ++ flags |= MSG_NOSIGNAL; ++#endif ++ return send(fd, data, length, flags); + } +diff --git a/common/socket.h b/common/socket.h +index 81ee083..e31de6b 100644 +--- a/common/socket.h ++++ b/common/socket.h +@@ -1,8 +1,8 @@ + /* + * socket.h + * +- * Copyright (c) 2012 Martin Szulecki All Rights Reserved. +- * Copyright (c) 2012 Nikias Bassen All Rights Reserved. ++ * Copyright (C) 2012 Martin Szulecki ++ * Copyright (C) 2012 Nikias Bassen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public +@@ -19,8 +19,8 @@ + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +-#ifndef __SOCKET_SOCKET_H +-#define __SOCKET_SOCKET_H ++#ifndef SOCKET_SOCKET_H ++#define SOCKET_SOCKET_H + + #include + #include +@@ -62,4 +62,4 @@ int socket_send(int fd, void *data, size_t size); + + void socket_set_verbose(int level); + +-#endif /* __SOCKET_SOCKET_H */ ++#endif /* SOCKET_SOCKET_H */ +-- +2.23.0 + + +From eb61c7b660fb58f9edb0f7b5507ebaad28422361 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Mon, 10 Jun 2019 04:11:43 +0200 +Subject: [PATCH 097/151] configure.ac: Fix --without-cython/--with-cython + logic + +--- + configure.ac | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 69ff13b..a2a5b12 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -66,17 +66,17 @@ if test "x$ac_cv_have_endian_h" = "xno"; then + fi + + # Check for operating system +-AC_MSG_CHECKING([whether we need platform-specific build settings]) ++AC_MSG_CHECKING([for platform-specific build settings]) + case ${host_os} in + *mingw32*|*cygwin*) +- AC_MSG_RESULT([yes]) ++ AC_MSG_RESULT([${host_os}]) + win32=true + ;; + darwin*) +- AC_MSG_RESULT([no]) ++ AC_MSG_RESULT([${host_os}]) + ;; + *) +- AC_MSG_RESULT([yes]) ++ AC_MSG_RESULT([${host_os}]) + AX_PTHREAD([], [AC_MSG_ERROR([pthread is required to build $PACKAGE_NAME])]) + AC_CHECK_LIB(pthread, [pthread_once], [], [AC_MSG_ERROR([pthread with pthread_once required to build $PACKAGE_NAME])]) + ;; +@@ -89,9 +89,9 @@ AC_CHECK_MEMBER(struct dirent.d_type, AC_DEFINE(HAVE_DIRENT_D_TYPE, 1, [define i + AC_ARG_WITH([cython], + [AS_HELP_STRING([--without-cython], + [build Python bindings using Cython (default is yes)])], +- [build_cython=false], +- [build_cython=true]) +-if test "$build_cython" = "true"; then ++ [build_cython=$withval], ++ [build_cython=yes]) ++if test "$build_cython" = "yes"; then + AM_PATH_PYTHON(2.3) + AC_PROG_CYTHON(0.17.0) + CYTHON_PYTHON +-- +2.23.0 + + +From 34444782e22ebfd2abc9e5e9c27e170a839ff66b Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Mon, 10 Jun 2019 05:03:14 +0200 +Subject: [PATCH 098/151] Make sure OpenSSL version checks don't fail when + using LibreSSL + +--- + src/idevice.c | 13 ++++++------- + 1 file changed, 6 insertions(+), 7 deletions(-) + +diff --git a/src/idevice.c b/src/idevice.c +index cb9bb5c..be29884 100644 +--- a/src/idevice.c ++++ b/src/idevice.c +@@ -2,8 +2,8 @@ + * idevice.c + * Device discovery and communication interface. + * ++ * Copyright (c) 2009-2019 Nikias Bassen. All Rights Reserved. + * Copyright (c) 2014 Martin Szulecki All Rights Reserved. +- * Copyright (c) 2009-2014 Nikias Bassen. All Rights Reserved. + * Copyright (c) 2008 Zach C. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or +@@ -37,7 +37,6 @@ + #ifdef HAVE_OPENSSL + #include + #include +- + #else + #include + #endif +@@ -49,7 +48,7 @@ + + #ifdef HAVE_OPENSSL + +-#if OPENSSL_VERSION_NUMBER < 0x10002000L ++#if OPENSSL_VERSION_NUMBER < 0x10002000L || defined(LIBRESSL_VERSION_NUMBER) + static void SSL_COMP_free_compression_methods(void) + { + sk_SSL_COMP_free(SSL_COMP_get_compression_methods()); +@@ -60,7 +59,7 @@ static void openssl_remove_thread_state(void) + { + /* ERR_remove_thread_state() is available since OpenSSL 1.0.0-beta1, but + * deprecated in OpenSSL 1.1.0 */ +-#if OPENSSL_VERSION_NUMBER < 0x10100000L ++#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) + #if OPENSSL_VERSION_NUMBER >= 0x10000001L + ERR_remove_thread_state(NULL); + #else +@@ -69,7 +68,7 @@ static void openssl_remove_thread_state(void) + #endif + } + +-#if OPENSSL_VERSION_NUMBER < 0x10100000L ++#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) + static mutex_t *mutex_buf = NULL; + static void locking_function(int mode, int n, const char* file, int line) + { +@@ -89,7 +88,7 @@ static unsigned long id_function(void) + static void internal_idevice_init(void) + { + #ifdef HAVE_OPENSSL +-#if OPENSSL_VERSION_NUMBER < 0x10100000L ++#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) + int i; + SSL_library_init(); + +@@ -110,7 +109,7 @@ static void internal_idevice_init(void) + static void internal_idevice_deinit(void) + { + #ifdef HAVE_OPENSSL +-#if OPENSSL_VERSION_NUMBER < 0x10100000L ++#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) + int i; + if (mutex_buf) { + CRYPTO_set_id_callback(NULL); +-- +2.23.0 + + +From 59adbacef6d400d4c6458f26daddda24bcdfd635 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Tue, 11 Jun 2019 01:12:49 +0200 +Subject: [PATCH 099/151] common: Update thread.c/.h to match the one from + libusbmuxd + +--- + common/thread.c | 48 ++++++++++++++++++++++++++++----- + common/thread.h | 33 ++++++++++++++++++----- + src/installation_proxy.c | 11 +++++--- + src/installation_proxy.h | 2 +- + src/notification_proxy.c | 6 ++--- + src/notification_proxy.h | 2 +- + src/syslog_relay.c | 8 +++--- + src/syslog_relay.h | 2 +- + tools/idevicedebugserverproxy.c | 6 ++--- + 9 files changed, 87 insertions(+), 31 deletions(-) + +diff --git a/common/thread.c b/common/thread.c +index fdc8112..eb535ab 100644 +--- a/common/thread.c ++++ b/common/thread.c +@@ -1,8 +1,8 @@ + /* + * thread.c + * +- * Copyright (c) 2012 Martin Szulecki All Rights Reserved. +- * Copyright (c) 2012 Nikias Bassen All Rights Reserved. ++ * Copyright (c) 2012-2019 Nikias Bassen, All Rights Reserved. ++ * Copyright (c) 2012 Martin Szulecki, All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public +@@ -19,9 +19,12 @@ + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + ++#ifdef HAVE_CONFIG_H ++#include ++#endif + #include "thread.h" + +-int thread_new(thread_t *thread, thread_func_t thread_func, void* data) ++int thread_new(THREAD_T *thread, thread_func_t thread_func, void* data) + { + #ifdef WIN32 + HANDLE th = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)thread_func, data, 0, NULL); +@@ -36,20 +39,51 @@ int thread_new(thread_t *thread, thread_func_t thread_func, void* data) + #endif + } + +-void thread_free(thread_t thread) ++void thread_detach(THREAD_T thread) + { + #ifdef WIN32 + CloseHandle(thread); ++#else ++ pthread_detach(thread); + #endif + } + +-void thread_join(thread_t thread) ++void thread_free(THREAD_T thread) ++{ ++#ifdef WIN32 ++ CloseHandle(thread); ++#endif ++} ++ ++int thread_join(THREAD_T thread) + { + /* wait for thread to complete */ + #ifdef WIN32 +- WaitForSingleObject(thread, INFINITE); ++ return (int)WaitForSingleObject(thread, INFINITE); ++#else ++ return pthread_join(thread, NULL); ++#endif ++} ++ ++int thread_alive(THREAD_T thread) ++{ ++#ifdef WIN32 ++ return WaitForSingleObject(thread, 0) == WAIT_TIMEOUT; + #else +- pthread_join(thread, NULL); ++ return pthread_kill(thread, 0) == 0; ++#endif ++} ++ ++int thread_cancel(THREAD_T thread) ++{ ++#ifdef WIN32 ++ return -1; ++#else ++#ifdef HAVE_PTHREAD_CANCEL ++ return pthread_cancel(thread); ++#else ++ return -1; ++#endif + #endif + } + +diff --git a/common/thread.h b/common/thread.h +index bd53c5b..23e4510 100644 +--- a/common/thread.h ++++ b/common/thread.h +@@ -1,8 +1,8 @@ + /* + * thread.h + * +- * Copyright (c) 2012 Martin Szulecki All Rights Reserved. +- * Copyright (c) 2012 Nikias Bassen All Rights Reserved. ++ * Copyright (c) 2012-2019 Nikias Bassen, All Rights Reserved. ++ * Copyright (c) 2012 Martin Szulecki, All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public +@@ -22,9 +22,11 @@ + #ifndef __THREAD_H + #define __THREAD_H + ++#include ++ + #ifdef WIN32 + #include +-typedef HANDLE thread_t; ++typedef HANDLE THREAD_T; + typedef CRITICAL_SECTION mutex_t; + typedef volatile struct { + LONG lock; +@@ -32,20 +34,37 @@ typedef volatile struct { + } thread_once_t; + #define THREAD_ONCE_INIT {0, 0} + #define THREAD_ID GetCurrentThreadId() ++#define THREAD_T_NULL (THREAD_T)NULL + #else + #include +-typedef pthread_t thread_t; ++#include ++typedef pthread_t THREAD_T; + typedef pthread_mutex_t mutex_t; + typedef pthread_once_t thread_once_t; + #define THREAD_ONCE_INIT PTHREAD_ONCE_INIT + #define THREAD_ID pthread_self() ++#define THREAD_T_NULL (THREAD_T)NULL + #endif + + typedef void* (*thread_func_t)(void* data); + +-int thread_new(thread_t* thread, thread_func_t thread_func, void* data); +-void thread_free(thread_t thread); +-void thread_join(thread_t thread); ++int thread_new(THREAD_T* thread, thread_func_t thread_func, void* data); ++void thread_detach(THREAD_T thread); ++void thread_free(THREAD_T thread); ++int thread_join(THREAD_T thread); ++int thread_alive(THREAD_T thread); ++ ++int thread_cancel(THREAD_T thread); ++ ++#ifdef WIN32 ++#undef HAVE_THREAD_CLEANUP ++#else ++#ifdef HAVE_PTHREAD_CANCEL ++#define HAVE_THREAD_CLEANUP 1 ++#define thread_cleanup_push(routine, arg) pthread_cleanup_push(routine, arg) ++#define thread_cleanup_pop(execute) pthread_cleanup_pop(execute) ++#endif ++#endif + + void mutex_init(mutex_t* mutex); + void mutex_destroy(mutex_t* mutex); +diff --git a/src/installation_proxy.c b/src/installation_proxy.c +index f82eecc..24044aa 100644 +--- a/src/installation_proxy.c ++++ b/src/installation_proxy.c +@@ -20,6 +20,9 @@ + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + ++#ifdef HAVE_CONFIG_H ++#include ++#endif + #include + #include + #include +@@ -240,7 +243,7 @@ LIBIMOBILEDEVICE_API instproxy_error_t instproxy_client_new(idevice_t device, lo + instproxy_client_t client_loc = (instproxy_client_t) malloc(sizeof(struct instproxy_client_private)); + client_loc->parent = plistclient; + mutex_init(&client_loc->mutex); +- client_loc->receive_status_thread = (thread_t)NULL; ++ client_loc->receive_status_thread = THREAD_T_NULL; + + *client = client_loc; + return INSTPROXY_E_SUCCESS; +@@ -264,7 +267,7 @@ LIBIMOBILEDEVICE_API instproxy_error_t instproxy_client_free(instproxy_client_t + debug_info("joining receive_status_thread"); + thread_join(client->receive_status_thread); + thread_free(client->receive_status_thread); +- client->receive_status_thread = (thread_t)NULL; ++ client->receive_status_thread = THREAD_T_NULL; + } + mutex_destroy(&client->mutex); + free(client); +@@ -343,7 +346,7 @@ static instproxy_error_t instproxy_receive_status_loop(instproxy_client_t client + + /* parse status response */ + if (node) { +- /* check status for possible error to allow reporting it and aborting it gracefully */ ++ /* check status for possible error to allow reporting it and aborting it gracefully */ + res = instproxy_status_get_error(node, &error_name, &error_description, &error_code); + if (res != INSTPROXY_E_SUCCESS) { + debug_info("command: %s, error %d, code 0x%08"PRIx64", name: %s, description: \"%s\"", command_name, res, error_code, error_name, error_description ? error_description: "N/A"); +@@ -431,7 +434,7 @@ static void* instproxy_receive_status_loop_thread(void* arg) + + if (data->client->receive_status_thread) { + thread_free(data->client->receive_status_thread); +- data->client->receive_status_thread = (thread_t)NULL; ++ data->client->receive_status_thread = THREAD_T_NULL; + } + + instproxy_unlock(data->client); +diff --git a/src/installation_proxy.h b/src/installation_proxy.h +index bbc14ce..66dd5d0 100644 +--- a/src/installation_proxy.h ++++ b/src/installation_proxy.h +@@ -30,7 +30,7 @@ + struct instproxy_client_private { + property_list_service_client_t parent; + mutex_t mutex; +- thread_t receive_status_thread; ++ THREAD_T receive_status_thread; + }; + + #endif +diff --git a/src/notification_proxy.c b/src/notification_proxy.c +index c0b216e..3015ed9 100644 +--- a/src/notification_proxy.c ++++ b/src/notification_proxy.c +@@ -98,7 +98,7 @@ LIBIMOBILEDEVICE_API np_error_t np_client_new(idevice_t device, lockdownd_servic + client_loc->parent = plistclient; + + mutex_init(&client_loc->mutex); +- client_loc->notifier = (thread_t)NULL; ++ client_loc->notifier = THREAD_T_NULL; + + *client = client_loc; + return NP_E_SUCCESS; +@@ -132,7 +132,7 @@ LIBIMOBILEDEVICE_API np_error_t np_client_free(np_client_t client) + debug_info("joining np callback"); + thread_join(client->notifier); + thread_free(client->notifier); +- client->notifier = (thread_t)NULL; ++ client->notifier = THREAD_T_NULL; + } else { + dict = NULL; + property_list_service_receive_plist(parent, &dict); +@@ -350,7 +350,7 @@ LIBIMOBILEDEVICE_API np_error_t np_set_notify_callback( np_client_t client, np_n + client->parent = NULL; + thread_join(client->notifier); + thread_free(client->notifier); +- client->notifier = (thread_t)NULL; ++ client->notifier = THREAD_T_NULL; + client->parent = parent; + } + +diff --git a/src/notification_proxy.h b/src/notification_proxy.h +index cc25a95..f641e25 100644 +--- a/src/notification_proxy.h ++++ b/src/notification_proxy.h +@@ -29,7 +29,7 @@ + struct np_client_private { + property_list_service_client_t parent; + mutex_t mutex; +- thread_t notifier; ++ THREAD_T notifier; + }; + + void* np_notifier(void* arg); +diff --git a/src/syslog_relay.c b/src/syslog_relay.c +index 29f4de5..3be84e0 100644 +--- a/src/syslog_relay.c ++++ b/src/syslog_relay.c +@@ -81,7 +81,7 @@ LIBIMOBILEDEVICE_API syslog_relay_error_t syslog_relay_client_new(idevice_t devi + + syslog_relay_client_t client_loc = (syslog_relay_client_t) malloc(sizeof(struct syslog_relay_client_private)); + client_loc->parent = parent; +- client_loc->worker = (thread_t)NULL; ++ client_loc->worker = THREAD_T_NULL; + + *client = client_loc; + +@@ -107,7 +107,7 @@ LIBIMOBILEDEVICE_API syslog_relay_error_t syslog_relay_client_free(syslog_relay_ + debug_info("Joining syslog capture callback worker thread"); + thread_join(client->worker); + thread_free(client->worker); +- client->worker = (thread_t)NULL; ++ client->worker = THREAD_T_NULL; + } + free(client); + +@@ -209,9 +209,9 @@ LIBIMOBILEDEVICE_API syslog_relay_error_t syslog_relay_stop_capture(syslog_relay + /* join thread to make it exit */ + thread_join(client->worker); + thread_free(client->worker); +- client->worker = (thread_t)NULL; ++ client->worker = THREAD_T_NULL; + client->parent = parent; + } + + return SYSLOG_RELAY_E_SUCCESS; +-} +\ No newline at end of file ++} +diff --git a/src/syslog_relay.h b/src/syslog_relay.h +index cd45775..3e48fa4 100644 +--- a/src/syslog_relay.h ++++ b/src/syslog_relay.h +@@ -28,7 +28,7 @@ + + struct syslog_relay_client_private { + service_client_t parent; +- thread_t worker; ++ THREAD_T worker; + }; + + void *syslog_relay_worker(void *arg); +diff --git a/tools/idevicedebugserverproxy.c b/tools/idevicedebugserverproxy.c +index 0b0419b..e99d0bf 100644 +--- a/tools/idevicedebugserverproxy.c ++++ b/tools/idevicedebugserverproxy.c +@@ -50,7 +50,7 @@ typedef struct { + } socket_info_t; + + struct thread_info { +- thread_t th; ++ THREAD_T th; + struct thread_info *next; + }; + +@@ -140,7 +140,7 @@ static void *thread_client_to_device(void *data) + int recv_len; + int sent; + char buffer[131072]; +- thread_t dtoc; ++ THREAD_T dtoc; + + debug("%s: started thread...\n", __func__); + +@@ -205,7 +205,7 @@ static void* connection_handler(void* data) + { + debugserver_error_t derr = DEBUGSERVER_E_SUCCESS; + socket_info_t* socket_info = (socket_info_t*)data; +- thread_t ctod; ++ THREAD_T ctod; + + debug("%s: client_fd = %d\n", __func__, socket_info->client_fd); + +-- +2.23.0 + + +From 0a3992b78afaf6d0cdbb782c18fc2dfca71e9468 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Tue, 11 Jun 2019 01:21:29 +0200 +Subject: [PATCH 100/151] m4: Update cython_python to use newer AX_PYTHON_DEVEL + macro + +--- + m4/cython_python.m4 | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/m4/cython_python.m4 b/m4/cython_python.m4 +index ba730d5..5b4a041 100644 +--- a/m4/cython_python.m4 ++++ b/m4/cython_python.m4 +@@ -1,6 +1,6 @@ + AC_DEFUN([CYTHON_PYTHON],[ + AC_REQUIRE([AC_PROG_CYTHON]) +- AC_REQUIRE([AC_PYTHON_DEVEL]) ++ AC_REQUIRE([AX_PYTHON_DEVEL]) + test "x$1" != "xno" || cython_shadow=" -noproxy" + AC_SUBST([CYTHON_PYTHON_OPT],[-python$cython_shadow]) + AC_SUBST([CYTHON_PYTHON_CPPFLAGS],[$PYTHON_CPPFLAGS]) +-- +2.23.0 + + +From 9920b6610eefcab7932bc8f951bf69a23d3f8d13 Mon Sep 17 00:00:00 2001 +From: Yves-Alexis Perez +Date: Tue, 11 Jun 2019 01:29:50 +0200 +Subject: [PATCH 101/151] Use _LIBS instead of _LDFLAGS for cython link + +Latest version of AX_PYTHON_DEVEL m4 macro use _LIBS and not LDFLAGS +--- + cython/Makefile.am | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/cython/Makefile.am b/cython/Makefile.am +index fb9a2e4..6aeaf08 100644 +--- a/cython/Makefile.am ++++ b/cython/Makefile.am +@@ -1,7 +1,7 @@ + AM_CPPFLAGS = -I$(top_srcdir)/include + +-AM_CFLAGS = $(GLOBAL_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(openssl_CFLAGS) $(libplist_CFLAGS) $(LFS_CFLAGS) +-AM_LDFLAGS = $(libgnutls_LIBS) $(libtasn1_LIBS) $(openssl_LIBS) $(libplist_LIBS) ++AM_CFLAGS = $(GLOBAL_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(openssl_CFLAGS) $(libplist_CFLAGS) $(LFS_CFLAGS) $(PTHREAD_CFLAGS) ++AM_LIBS = $(libgnutls_LIBS) $(libtasn1_LIBS) $(openssl_LIBS) $(libplist_LIBS) $(PTHREAD_LIBS) + + if HAVE_CYTHON + +@@ -38,7 +38,7 @@ imobiledevicedir = $(pyexecdir) + imobiledevice_LTLIBRARIES = imobiledevice.la + imobiledevice_la_SOURCES = imobiledevice.pyx + imobiledevice_la_CFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/src $(PYTHON_CPPFLAGS) $(AM_CFLAGS) -Wno-shadow -Wno-redundant-decls -Wno-switch-default -Wno-strict-aliasing -Wno-implicit-function-declaration -fvisibility=default +-imobiledevice_la_LDFLAGS = -module -avoid-version -L$(libdir) $(PYTHON_LDFLAGS) $(AM_LDFLAGS) -no-undefined ++imobiledevice_la_LDFLAGS = -module -avoid-version -L$(libdir) $(PYTHON_LIBS) $(AM_LIBS) -no-undefined + imobiledevice_la_LIBADD = $(top_builddir)/src/libimobiledevice.la + + imobiledevice.c: imobiledevice.pyx $(PXDINCLUDES) $(PXIINCLUDES) +-- +2.23.0 + + +From 6edc36fccb52a963c9ebfbb44ba7b91570e0fd06 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Thu, 13 Jun 2019 00:56:32 +0200 +Subject: [PATCH 103/151] socket: Return -ETIMEDOUT when select() in + socket_read_fd() reached the timeout + +--- + common/socket.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/common/socket.c b/common/socket.c +index aa97848..0ee8105 100644 +--- a/common/socket.c ++++ b/common/socket.c +@@ -412,6 +412,10 @@ int socket_check_fd(int fd, fd_mode fdm, unsigned int timeout) + strerror(errno)); + return -1; + } ++ } else if (sret == 0) { ++ if (verbose >= 2) ++ fprintf(stderr, "%s: timeout\n", __func__); ++ return -ETIMEDOUT; + } + } while (eagain); + +-- +2.23.0 + + +From 4d8b89223cbc9f530cc650ab5131c09eab1af258 Mon Sep 17 00:00:00 2001 +From: DanyL +Date: Thu, 13 Jun 2019 02:01:04 +0300 +Subject: [PATCH 104/151] Timeout support for SSL connections and better + timeout handeling. + +--- + cython/heartbeat.pxi | 4 + + cython/imobiledevice.pyx | 6 +- + cython/webinspector.pxi | 2 + + include/libimobiledevice/heartbeat.h | 16 ++- + include/libimobiledevice/libimobiledevice.h | 4 +- + .../libimobiledevice/property_list_service.h | 3 + + include/libimobiledevice/service.h | 10 +- + include/libimobiledevice/webinspector.h | 14 ++- + src/heartbeat.c | 4 + + src/idevice.c | 59 +++++++-- + src/property_list_service.c | 116 +++++++++--------- + src/service.c | 7 +- + src/webinspector.c | 4 + + tools/idevicecrashreport.c | 2 +- + 14 files changed, 163 insertions(+), 88 deletions(-) + +diff --git a/cython/heartbeat.pxi b/cython/heartbeat.pxi +index b48fb59..2f58909 100644 +--- a/cython/heartbeat.pxi ++++ b/cython/heartbeat.pxi +@@ -9,6 +9,8 @@ cdef extern from "libimobiledevice/heartbeat.h": + HEARTBEAT_E_PLIST_ERROR = -2 + HEARTBEAT_E_MUX_ERROR = -3 + HEARTBEAT_E_SSL_ERROR = -4 ++ HEARTBEAT_E_NOT_ENOUGH_DATA = -5 ++ HEARTBEAT_E_TIMEOUT = -6 + HEARTBEAT_E_UNKNOWN_ERROR = -256 + + heartbeat_error_t heartbeat_client_new(idevice_t device, lockdownd_service_descriptor_t descriptor, heartbeat_client_t * client) +@@ -26,6 +28,8 @@ cdef class HeartbeatError(BaseError): + HEARTBEAT_E_PLIST_ERROR: "Property list error", + HEARTBEAT_E_MUX_ERROR: "MUX error", + HEARTBEAT_E_SSL_ERROR: "SSL Error", ++ HEARTBEAT_E_NOT_ENOUGH_DATA: 'Not enough data', ++ HEARTBEAT_E_TIMEOUT: 'Connection timeout', + HEARTBEAT_E_UNKNOWN_ERROR: "Unknown error" + } + BaseError.__init__(self, *args, **kwargs) +diff --git a/cython/imobiledevice.pyx b/cython/imobiledevice.pyx +index bc861b3..141f67c 100644 +--- a/cython/imobiledevice.pyx ++++ b/cython/imobiledevice.pyx +@@ -38,8 +38,8 @@ cdef extern from "libimobiledevice/libimobiledevice.h": + IDEVICE_E_UNKNOWN_ERROR = -2 + IDEVICE_E_NO_DEVICE = -3 + IDEVICE_E_NOT_ENOUGH_DATA = -4 +- IDEVICE_E_BAD_HEADER = -5 + IDEVICE_E_SSL_ERROR = -6 ++ IDEVICE_E_TIMEOUT = -7 + ctypedef void (*idevice_event_cb_t) (const_idevice_event_t event, void *user_data) + cdef extern idevice_error_t idevice_event_subscribe(idevice_event_cb_t callback, void *user_data) + cdef extern idevice_error_t idevice_event_unsubscribe() +@@ -64,8 +64,8 @@ cdef class iDeviceError(BaseError): + IDEVICE_E_UNKNOWN_ERROR: 'Unknown error', + IDEVICE_E_NO_DEVICE: 'No device', + IDEVICE_E_NOT_ENOUGH_DATA: 'Not enough data', +- IDEVICE_E_BAD_HEADER: 'Bad header', +- IDEVICE_E_SSL_ERROR: 'SSL Error' ++ IDEVICE_E_SSL_ERROR: 'SSL Error', ++ IDEVICE_E_TIMEOUT: 'Connection timeout' + } + BaseError.__init__(self, *args, **kwargs) + +diff --git a/cython/webinspector.pxi b/cython/webinspector.pxi +index 4622ef5..eb9fba1 100644 +--- a/cython/webinspector.pxi ++++ b/cython/webinspector.pxi +@@ -26,6 +26,8 @@ cdef class WebinspectorError(BaseError): + WEBINSPECTOR_E_PLIST_ERROR: "Property list error", + WEBINSPECTOR_E_MUX_ERROR: "MUX error", + WEBINSPECTOR_E_SSL_ERROR: "SSL Error", ++ WEBINSPECTOR_E_NOT_ENOUGH_DATA: 'Not enough data', ++ WEBINSPECTOR_E_TIMEOUT: 'Connection timeout', + WEBINSPECTOR_E_UNKNOWN_ERROR: "Unknown error" + } + BaseError.__init__(self, *args, **kwargs) +diff --git a/include/libimobiledevice/heartbeat.h b/include/libimobiledevice/heartbeat.h +index 00734b5..1f5344a 100644 +--- a/include/libimobiledevice/heartbeat.h ++++ b/include/libimobiledevice/heartbeat.h +@@ -34,12 +34,14 @@ extern "C" { + + /** Error Codes */ + typedef enum { +- HEARTBEAT_E_SUCCESS = 0, +- HEARTBEAT_E_INVALID_ARG = -1, +- HEARTBEAT_E_PLIST_ERROR = -2, +- HEARTBEAT_E_MUX_ERROR = -3, +- HEARTBEAT_E_SSL_ERROR = -4, +- HEARTBEAT_E_UNKNOWN_ERROR = -256 ++ HEARTBEAT_E_SUCCESS = 0, ++ HEARTBEAT_E_INVALID_ARG = -1, ++ HEARTBEAT_E_PLIST_ERROR = -2, ++ HEARTBEAT_E_MUX_ERROR = -3, ++ HEARTBEAT_E_SSL_ERROR = -4, ++ HEARTBEAT_E_NOT_ENOUGH_DATA = -5, ++ HEARTBEAT_E_TIMEOUT = -6, ++ HEARTBEAT_E_UNKNOWN_ERROR = -256 + } heartbeat_error_t; + + typedef struct heartbeat_client_private heartbeat_client_private; +@@ -118,6 +120,8 @@ heartbeat_error_t heartbeat_receive(heartbeat_client_t client, plist_t * plist); + * + * @return HEARTBEAT_E_SUCCESS on success, + * HEARTBEAT_E_INVALID_ARG when client or *plist is NULL, ++ * HEARTBEAT_E_NOT_ENOUGH_DATA when not enough data ++ * received, HEARTBEAT_E_TIMEOUT when the connection times out, + * HEARTBEAT_E_PLIST_ERROR when the received data cannot be + * converted to a plist, HEARTBEAT_E_MUX_ERROR when a + * communication error occurs, or HEARTBEAT_E_UNKNOWN_ERROR +diff --git a/include/libimobiledevice/libimobiledevice.h b/include/libimobiledevice/libimobiledevice.h +index 5ec1a6d..729bc89 100644 +--- a/include/libimobiledevice/libimobiledevice.h ++++ b/include/libimobiledevice/libimobiledevice.h +@@ -41,8 +41,8 @@ typedef enum { + IDEVICE_E_UNKNOWN_ERROR = -2, + IDEVICE_E_NO_DEVICE = -3, + IDEVICE_E_NOT_ENOUGH_DATA = -4, +- IDEVICE_E_BAD_HEADER = -5, +- IDEVICE_E_SSL_ERROR = -6 ++ IDEVICE_E_SSL_ERROR = -6, ++ IDEVICE_E_TIMEOUT = -7 + } idevice_error_t; + + typedef struct idevice_private idevice_private; +diff --git a/include/libimobiledevice/property_list_service.h b/include/libimobiledevice/property_list_service.h +index 5d5b835..aca966d 100644 +--- a/include/libimobiledevice/property_list_service.h ++++ b/include/libimobiledevice/property_list_service.h +@@ -38,6 +38,7 @@ typedef enum { + PROPERTY_LIST_SERVICE_E_MUX_ERROR = -3, + PROPERTY_LIST_SERVICE_E_SSL_ERROR = -4, + PROPERTY_LIST_SERVICE_E_RECEIVE_TIMEOUT = -5, ++ PROPERTY_LIST_SERVICE_E_NOT_ENOUGH_DATA = -6, + PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR = -256 + } property_list_service_error_t; + +@@ -130,6 +131,8 @@ property_list_service_error_t property_list_service_receive_plist_with_timeout(p + * + * @return PROPERTY_LIST_SERVICE_E_SUCCESS on success, + * PROPERTY_LIST_SERVICE_E_INVALID_ARG when client or *plist is NULL, ++ * PROPERTY_LIST_SERVICE_E_NOT_ENOUGH_DATA when not enough data ++ * received, PROPERTY_LIST_SERVICE_E_RECEIVE_TIMEOUT when the connection times out, + * PROPERTY_LIST_SERVICE_E_PLIST_ERROR when the received data cannot be + * converted to a plist, PROPERTY_LIST_SERVICE_E_MUX_ERROR when a + * communication error occurs, or PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR when +diff --git a/include/libimobiledevice/service.h b/include/libimobiledevice/service.h +index 13c5df1..5c43e29 100644 +--- a/include/libimobiledevice/service.h ++++ b/include/libimobiledevice/service.h +@@ -37,6 +37,8 @@ typedef enum { + SERVICE_E_MUX_ERROR = -3, + SERVICE_E_SSL_ERROR = -4, + SERVICE_E_START_SERVICE_ERROR = -5, ++ SERIVCE_E_NOT_ENOUGH_DATA = -6, ++ SERVICE_E_TIMEOUT = -7, + SERVICE_E_UNKNOWN_ERROR = -256 + } service_error_t; + +@@ -132,7 +134,9 @@ service_error_t service_receive_with_timeout(service_client_t client, char *data + * + * @return SERVICE_E_SUCCESS on success, + * SERVICE_E_INVALID_ARG when one or more parameters are +- * invalid, SERVICE_E_MUX_ERROR when a communication error ++ * invalid, SERIVCE_E_NOT_ENOUGH_DATA when not enough data ++ * received, SERVICE_E_TIMEOUT when the connection times out, ++ * SERVICE_E_MUX_ERROR when a communication error + * occurs, or SERVICE_E_UNKNOWN_ERROR when an unspecified + * error occurs. + */ +@@ -146,7 +150,9 @@ service_error_t service_receive(service_client_t client, char *data, uint32_t si + * + * @return SERVICE_E_SUCCESS on success, + * SERVICE_E_INVALID_ARG if client or client->connection is +- * NULL, SERVICE_E_SSL_ERROR when SSL could not be enabled, ++ * NULL, SERIVCE_E_NOT_ENOUGH_DATA when not enough data ++ * received, SERVICE_E_TIMEOUT when the connection times out, ++ * SERVICE_E_SSL_ERROR when SSL could not be enabled, + * or SERVICE_E_UNKNOWN_ERROR otherwise. + */ + service_error_t service_enable_ssl(service_client_t client); +diff --git a/include/libimobiledevice/webinspector.h b/include/libimobiledevice/webinspector.h +index d2a99c9..da0759c 100644 +--- a/include/libimobiledevice/webinspector.h ++++ b/include/libimobiledevice/webinspector.h +@@ -35,12 +35,14 @@ extern "C" { + + /** Error Codes */ + typedef enum { +- WEBINSPECTOR_E_SUCCESS = 0, +- WEBINSPECTOR_E_INVALID_ARG = -1, +- WEBINSPECTOR_E_PLIST_ERROR = -2, +- WEBINSPECTOR_E_MUX_ERROR = -3, +- WEBINSPECTOR_E_SSL_ERROR = -4, +- WEBINSPECTOR_E_UNKNOWN_ERROR = -256 ++ WEBINSPECTOR_E_SUCCESS = 0, ++ WEBINSPECTOR_E_INVALID_ARG = -1, ++ WEBINSPECTOR_E_PLIST_ERROR = -2, ++ WEBINSPECTOR_E_MUX_ERROR = -3, ++ WEBINSPECTOR_E_SSL_ERROR = -4, ++ WEBINSPECTOR_E_RECEIVE_TIMEOUT = -5, ++ WEBINSPECTOR_E_NOT_ENOUGH_DATA = -6, ++ WEBINSPECTOR_E_UNKNOWN_ERROR = -256 + } webinspector_error_t; + + typedef struct webinspector_client_private webinspector_client_private; +diff --git a/src/heartbeat.c b/src/heartbeat.c +index fe7e63a..9a527cc 100644 +--- a/src/heartbeat.c ++++ b/src/heartbeat.c +@@ -52,6 +52,10 @@ static heartbeat_error_t heartbeat_error(property_list_service_error_t err) + return HEARTBEAT_E_MUX_ERROR; + case PROPERTY_LIST_SERVICE_E_SSL_ERROR: + return HEARTBEAT_E_SSL_ERROR; ++ case PROPERTY_LIST_SERVICE_E_NOT_ENOUGH_DATA: ++ return HEARTBEAT_E_NOT_ENOUGH_DATA; ++ case PROPERTY_LIST_SERVICE_E_RECEIVE_TIMEOUT: ++ return HEARTBEAT_E_TIMEOUT; + default: + break; + } +diff --git a/src/idevice.c b/src/idevice.c +index be29884..5d5c950 100644 +--- a/src/idevice.c ++++ b/src/idevice.c +@@ -43,6 +43,7 @@ + + #include "idevice.h" + #include "common/userpref.h" ++#include "common/socket.h" + #include "common/thread.h" + #include "common/debug.h" + +@@ -381,6 +382,24 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_send(idevice_connection_ + return internal_connection_send(connection, data, len, sent_bytes); + } + ++static idevice_error_t socket_recv_to_idevice_error(int conn_error, uint32_t len, uint32_t received) ++{ ++ if (conn_error < 0) { ++ switch (conn_error) { ++ case -EAGAIN: ++ debug_info("ERROR: received partial data %d/%d (%s)", received, len, strerror(-conn_error)); ++ return IDEVICE_E_NOT_ENOUGH_DATA; ++ case -ETIMEDOUT: ++ debug_info("ERROR: received timeout (%s)", strerror(-conn_error)); ++ return IDEVICE_E_TIMEOUT; ++ default: ++ return IDEVICE_E_UNKNOWN_ERROR; ++ } ++ } ++ ++ return IDEVICE_E_SUCCESS; ++} ++ + /** + * Internally used function for receiving raw data over the given connection + * using a timeout. +@@ -392,12 +411,14 @@ static idevice_error_t internal_connection_receive_timeout(idevice_connection_t + } + + if (connection->type == CONNECTION_USBMUXD) { +- int res = usbmuxd_recv_timeout((int)(long)connection->data, data, len, recv_bytes, timeout); +- if (res < 0) { +- debug_info("ERROR: usbmuxd_recv_timeout returned %d (%s)", res, strerror(errno)); +- return (res == -EAGAIN ? IDEVICE_E_NOT_ENOUGH_DATA : IDEVICE_E_UNKNOWN_ERROR); ++ int conn_error = usbmuxd_recv_timeout((int)(long)connection->data, data, len, recv_bytes, timeout); ++ idevice_error_t error = socket_recv_to_idevice_error(conn_error, len, *recv_bytes); ++ ++ if (error == IDEVICE_E_UNKNOWN_ERROR) { ++ debug_info("ERROR: usbmuxd_recv_timeout returned %d (%s)", conn_error, strerror(-conn_error)); + } +- return IDEVICE_E_SUCCESS; ++ ++ return error; + } else { + debug_info("Unknown connection type %d", connection->type); + } +@@ -406,13 +427,27 @@ static idevice_error_t internal_connection_receive_timeout(idevice_connection_t + + LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_receive_timeout(idevice_connection_t connection, char *data, uint32_t len, uint32_t *recv_bytes, unsigned int timeout) + { +- if (!connection || (connection->ssl_data && !connection->ssl_data->session)) { ++ if (!connection || (connection->ssl_data && !connection->ssl_data->session) || len == 0) { + return IDEVICE_E_INVALID_ARG; + } + + if (connection->ssl_data) { + uint32_t received = 0; ++ + while (received < len) { ++ ++ int conn_error = socket_check_fd((int)(long)connection->data, FDM_READ, timeout); ++ idevice_error_t error = socket_recv_to_idevice_error(conn_error, len, received); ++ ++ switch (error) { ++ case IDEVICE_E_SUCCESS: ++ break; ++ case IDEVICE_E_UNKNOWN_ERROR: ++ debug_info("ERROR: socket_check_fd returned %d (%s)", conn_error, strerror(-conn_error)); ++ default: ++ return error; ++ } ++ + #ifdef HAVE_OPENSSL + int r = SSL_read(connection->ssl_data->session, (void*)((char*)(data+received)), (int)len-received); + #else +@@ -424,13 +459,15 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_receive_timeout(idevice_ + break; + } + } ++ + debug_info("SSL_read %d, received %d", len, received); +- if (received > 0) { +- *recv_bytes = received; +- return IDEVICE_E_SUCCESS; ++ if (received < len) { ++ *recv_bytes = 0; ++ return IDEVICE_E_SSL_ERROR; + } +- *recv_bytes = 0; +- return IDEVICE_E_SSL_ERROR; ++ ++ *recv_bytes = received; ++ return IDEVICE_E_SUCCESS; + } + return internal_connection_receive_timeout(connection, data, len, recv_bytes, timeout); + } +diff --git a/src/property_list_service.c b/src/property_list_service.c +index f411699..a6e3e24 100644 +--- a/src/property_list_service.c ++++ b/src/property_list_service.c +@@ -48,6 +48,10 @@ static property_list_service_error_t service_to_property_list_service_error(serv + return PROPERTY_LIST_SERVICE_E_MUX_ERROR; + case SERVICE_E_SSL_ERROR: + return PROPERTY_LIST_SERVICE_E_SSL_ERROR; ++ case SERIVCE_E_NOT_ENOUGH_DATA: ++ return PROPERTY_LIST_SERVICE_E_NOT_ENOUGH_DATA; ++ case SERVICE_E_TIMEOUT: ++ return PROPERTY_LIST_SERVICE_E_RECEIVE_TIMEOUT; + default: + break; + } +@@ -108,7 +112,7 @@ static property_list_service_error_t internal_plist_send(property_list_service_c + char *content = NULL; + uint32_t length = 0; + uint32_t nlen = 0; +- int bytes = 0; ++ uint32_t bytes = 0; + + if (!client || (client && !client->parent) || !plist) { + return PROPERTY_LIST_SERVICE_E_INVALID_ARG; +@@ -126,13 +130,13 @@ static property_list_service_error_t internal_plist_send(property_list_service_c + + nlen = htobe32(length); + debug_info("sending %d bytes", length); +- service_send(client->parent, (const char*)&nlen, sizeof(nlen), (uint32_t*)&bytes); ++ service_send(client->parent, (const char*)&nlen, sizeof(nlen), &bytes); + if (bytes == sizeof(nlen)) { +- service_send(client->parent, content, length, (uint32_t*)&bytes); ++ service_send(client->parent, content, length, &bytes); + if (bytes > 0) { + debug_info("sent %d bytes", bytes); + debug_plist(plist); +- if ((uint32_t)bytes == length) { ++ if (bytes == length) { + res = PROPERTY_LIST_SERVICE_E_SUCCESS; + } else { + debug_info("ERROR: Could not send all data (%d of %d)!", bytes, length); +@@ -145,7 +149,6 @@ static property_list_service_error_t internal_plist_send(property_list_service_c + } + + free(content); +- + return res; + } + +@@ -170,6 +173,8 @@ LIBIMOBILEDEVICE_API property_list_service_error_t property_list_service_send_bi + * + * @return PROPERTY_LIST_SERVICE_E_SUCCESS on success, + * PROPERTY_LIST_SERVICE_E_INVALID_ARG when client or *plist is NULL, ++ * PROPERTY_LIST_SERVICE_E_NOT_ENOUGH_DATA when not enough data ++ * received, PROPERTY_LIST_SERVICE_E_RECEIVE_TIMEOUT when the connection times out, + * PROPERTY_LIST_SERVICE_E_PLIST_ERROR when the received data cannot be + * converted to a plist, PROPERTY_LIST_SERVICE_E_MUX_ERROR when a + * communication error occurs, or PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR +@@ -187,65 +192,64 @@ static property_list_service_error_t internal_plist_receive_timeout(property_lis + + *plist = NULL; + service_error_t serr = service_receive_with_timeout(client->parent, (char*)&pktlen, sizeof(pktlen), &bytes, timeout); +- if ((serr == SERVICE_E_SUCCESS) && (bytes == 0)) { +- return PROPERTY_LIST_SERVICE_E_RECEIVE_TIMEOUT; ++ if (serr != SERVICE_E_SUCCESS) { ++ debug_info("initial read failed!"); ++ return service_to_property_list_service_error(serr); + } ++ + debug_info("initial read=%i", bytes); +- if (bytes < 4) { +- debug_info("initial read failed!"); +- return PROPERTY_LIST_SERVICE_E_MUX_ERROR; +- } else { +- uint32_t curlen = 0; +- char *content = NULL; + +- pktlen = be32toh(pktlen); +- debug_info("%d bytes following", pktlen); +- content = (char*)malloc(pktlen); +- if (!content) { +- debug_info("out of memory when allocating %d bytes", pktlen); +- return PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR; +- } ++ uint32_t curlen = 0; ++ char *content = NULL; + +- while (curlen < pktlen) { +- service_receive(client->parent, content+curlen, pktlen-curlen, &bytes); +- if (bytes <= 0) { +- res = PROPERTY_LIST_SERVICE_E_MUX_ERROR; +- break; +- } +- debug_info("received %d bytes", bytes); +- curlen += bytes; +- } +- if (curlen < pktlen) { +- debug_info("received incomplete packet (%d of %d bytes)", curlen, pktlen); +- if (curlen > 0) { +- debug_info("incomplete packet following:"); +- debug_buffer(content, curlen); +- } +- free(content); +- return res; +- } +- if ((pktlen > 8) && !memcmp(content, "bplist00", 8)) { +- plist_from_bin(content, pktlen, plist); +- } else if ((pktlen > 5) && !memcmp(content, "= 0) && (content[bytes] < 0x20) && (content[bytes] != 0x09) && (content[bytes] != 0x0a) && (content[bytes] != 0x0d)) +- content[bytes] = 0x20; +- } +- plist_from_xml(content, pktlen, plist); +- } else { +- debug_info("WARNING: received unexpected non-plist content"); +- debug_buffer(content, pktlen); ++ pktlen = be32toh(pktlen); ++ debug_info("%d bytes following", pktlen); ++ content = (char*)malloc(pktlen); ++ if (!content) { ++ debug_info("out of memory when allocating %d bytes", pktlen); ++ return PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR; ++ } ++ ++ while (curlen < pktlen) { ++ serr = service_receive(client->parent, content+curlen, pktlen-curlen, &bytes); ++ if (serr != SERVICE_E_SUCCESS) { ++ res = service_to_property_list_service_error(serr); ++ break; + } +- if (*plist) { +- debug_plist(*plist); +- res = PROPERTY_LIST_SERVICE_E_SUCCESS; +- } else { +- res = PROPERTY_LIST_SERVICE_E_PLIST_ERROR; ++ debug_info("received %d bytes", bytes); ++ curlen += bytes; ++ } ++ if (curlen < pktlen) { ++ debug_info("received incomplete packet (%d of %d bytes)", curlen, pktlen); ++ if (curlen > 0) { ++ debug_info("incomplete packet following:"); ++ debug_buffer(content, curlen); + } + free(content); +- content = NULL; ++ return res; + } ++ if ((pktlen > 8) && !memcmp(content, "bplist00", 8)) { ++ plist_from_bin(content, pktlen, plist); ++ } else if ((pktlen > 5) && !memcmp(content, "= 0) && (content[bytes] < 0x20) && (content[bytes] != 0x09) && (content[bytes] != 0x0a) && (content[bytes] != 0x0d)) ++ content[bytes] = 0x20; ++ } ++ plist_from_xml(content, pktlen, plist); ++ } else { ++ debug_info("WARNING: received unexpected non-plist content"); ++ debug_buffer(content, pktlen); ++ } ++ if (*plist) { ++ debug_plist(*plist); ++ res = PROPERTY_LIST_SERVICE_E_SUCCESS; ++ } else { ++ res = PROPERTY_LIST_SERVICE_E_PLIST_ERROR; ++ } ++ free(content); ++ content = NULL; ++ + return res; + } + +diff --git a/src/service.c b/src/service.c +index 2dc42b2..57d987c 100644 +--- a/src/service.c ++++ b/src/service.c +@@ -46,6 +46,10 @@ static service_error_t idevice_to_service_error(idevice_error_t err) + return SERVICE_E_INVALID_ARG; + case IDEVICE_E_SSL_ERROR: + return SERVICE_E_SSL_ERROR; ++ case IDEVICE_E_NOT_ENOUGH_DATA: ++ return SERIVCE_E_NOT_ENOUGH_DATA; ++ case IDEVICE_E_TIMEOUT: ++ return SERVICE_E_TIMEOUT; + default: + break; + } +@@ -159,8 +163,9 @@ LIBIMOBILEDEVICE_API service_error_t service_receive_with_timeout(service_client + } + + res = idevice_to_service_error(idevice_connection_receive_timeout(client->connection, data, size, (uint32_t*)&bytes, timeout)); +- if (bytes <= 0) { ++ if (res != SERVICE_E_SUCCESS) { + debug_info("could not read data"); ++ return res; + } + if (received) { + *received = (uint32_t)bytes; +diff --git a/src/webinspector.c b/src/webinspector.c +index c81f4c7..3360597 100644 +--- a/src/webinspector.c ++++ b/src/webinspector.c +@@ -52,6 +52,10 @@ static webinspector_error_t webinspector_error(property_list_service_error_t err + return WEBINSPECTOR_E_MUX_ERROR; + case PROPERTY_LIST_SERVICE_E_SSL_ERROR: + return WEBINSPECTOR_E_SSL_ERROR; ++ case PROPERTY_LIST_SERVICE_E_RECEIVE_TIMEOUT: ++ return WEBINSPECTOR_E_RECEIVE_TIMEOUT; ++ case PROPERTY_LIST_SERVICE_E_NOT_ENOUGH_DATA: ++ return WEBINSPECTOR_E_NOT_ENOUGH_DATA; + default: + break; + } +diff --git a/tools/idevicecrashreport.c b/tools/idevicecrashreport.c +index e05d506..6918d6b 100644 +--- a/tools/idevicecrashreport.c ++++ b/tools/idevicecrashreport.c +@@ -411,7 +411,7 @@ int main(int argc, char* argv[]) { + while ((strncmp(ping, "ping", 4) != 0) && (attempts < 10)) { + uint32_t bytes = 0; + device_error = idevice_connection_receive_timeout(connection, ping, 4, &bytes, 2000); +- if ((bytes == 0) && (device_error == IDEVICE_E_SUCCESS)) { ++ if (device_error != IDEVICE_E_SUCCESS) { + attempts++; + continue; + } else if (device_error < 0) { +-- +2.23.0 + + +From fff10db8632bd9eb9e3a8c93146d1c77fe4a3b01 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Thu, 13 Jun 2019 01:47:16 +0200 +Subject: [PATCH 105/151] cyhton: Fix webinspector.pxi having undefined error + types + +--- + cython/webinspector.pxi | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/cython/webinspector.pxi b/cython/webinspector.pxi +index eb9fba1..f77547d 100644 +--- a/cython/webinspector.pxi ++++ b/cython/webinspector.pxi +@@ -9,6 +9,8 @@ cdef extern from "libimobiledevice/webinspector.h": + WEBINSPECTOR_E_PLIST_ERROR = -2 + WEBINSPECTOR_E_MUX_ERROR = -3 + WEBINSPECTOR_E_SSL_ERROR = -4 ++ WEBINSPECTOR_E_RECEIVE_TIMEOUT = -5, ++ WEBINSPECTOR_E_NOT_ENOUGH_DATA = -6, + WEBINSPECTOR_E_UNKNOWN_ERROR = -256 + + webinspector_error_t webinspector_client_new(idevice_t device, lockdownd_service_descriptor_t descriptor, webinspector_client_t * client) +@@ -27,7 +29,7 @@ cdef class WebinspectorError(BaseError): + WEBINSPECTOR_E_MUX_ERROR: "MUX error", + WEBINSPECTOR_E_SSL_ERROR: "SSL Error", + WEBINSPECTOR_E_NOT_ENOUGH_DATA: 'Not enough data', +- WEBINSPECTOR_E_TIMEOUT: 'Connection timeout', ++ WEBINSPECTOR_E_RECEIVE_TIMEOUT: 'Connection timeout', + WEBINSPECTOR_E_UNKNOWN_ERROR: "Unknown error" + } + BaseError.__init__(self, *args, **kwargs) +-- +2.23.0 + + +From 7c00b369a3665cd0aeae228b2a2866da8ee027fd Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Fri, 14 Jun 2019 18:32:37 +0200 +Subject: [PATCH 106/151] debugserver: Fix for iOS 13 + +--- + src/debugserver.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/debugserver.c b/src/debugserver.c +index 41546dd..1e06233 100644 +--- a/src/debugserver.c ++++ b/src/debugserver.c +@@ -77,6 +77,7 @@ LIBIMOBILEDEVICE_API debugserver_error_t debugserver_client_new(idevice_t device + debug_info("Creating base service client failed. Error: %i", ret); + return ret; + } ++ service_disable_ssl(parent); + + debugserver_client_t client_loc = (debugserver_client_t) malloc(sizeof(struct debugserver_client_private)); + client_loc->parent = parent; +-- +2.23.0 + + +From 1369f43fd5cf06e983f6399971d64284d39c9ddd Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Sun, 16 Jun 2019 01:16:01 +0200 +Subject: [PATCH 107/151] service: Fix typo SERIVCE_E_NOT_ENOUGH_DATA to + SERVICE_E_NOT_ENOUGH_DATA + +--- + include/libimobiledevice/service.h | 6 +++--- + src/property_list_service.c | 2 +- + src/service.c | 2 +- + 3 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/include/libimobiledevice/service.h b/include/libimobiledevice/service.h +index 5c43e29..facf03b 100644 +--- a/include/libimobiledevice/service.h ++++ b/include/libimobiledevice/service.h +@@ -37,7 +37,7 @@ typedef enum { + SERVICE_E_MUX_ERROR = -3, + SERVICE_E_SSL_ERROR = -4, + SERVICE_E_START_SERVICE_ERROR = -5, +- SERIVCE_E_NOT_ENOUGH_DATA = -6, ++ SERVICE_E_NOT_ENOUGH_DATA = -6, + SERVICE_E_TIMEOUT = -7, + SERVICE_E_UNKNOWN_ERROR = -256 + } service_error_t; +@@ -134,7 +134,7 @@ service_error_t service_receive_with_timeout(service_client_t client, char *data + * + * @return SERVICE_E_SUCCESS on success, + * SERVICE_E_INVALID_ARG when one or more parameters are +- * invalid, SERIVCE_E_NOT_ENOUGH_DATA when not enough data ++ * invalid, SERVICE_E_NOT_ENOUGH_DATA when not enough data + * received, SERVICE_E_TIMEOUT when the connection times out, + * SERVICE_E_MUX_ERROR when a communication error + * occurs, or SERVICE_E_UNKNOWN_ERROR when an unspecified +@@ -150,7 +150,7 @@ service_error_t service_receive(service_client_t client, char *data, uint32_t si + * + * @return SERVICE_E_SUCCESS on success, + * SERVICE_E_INVALID_ARG if client or client->connection is +- * NULL, SERIVCE_E_NOT_ENOUGH_DATA when not enough data ++ * NULL, SERVICE_E_NOT_ENOUGH_DATA when not enough data + * received, SERVICE_E_TIMEOUT when the connection times out, + * SERVICE_E_SSL_ERROR when SSL could not be enabled, + * or SERVICE_E_UNKNOWN_ERROR otherwise. +diff --git a/src/property_list_service.c b/src/property_list_service.c +index a6e3e24..1cb8dc9 100644 +--- a/src/property_list_service.c ++++ b/src/property_list_service.c +@@ -48,7 +48,7 @@ static property_list_service_error_t service_to_property_list_service_error(serv + return PROPERTY_LIST_SERVICE_E_MUX_ERROR; + case SERVICE_E_SSL_ERROR: + return PROPERTY_LIST_SERVICE_E_SSL_ERROR; +- case SERIVCE_E_NOT_ENOUGH_DATA: ++ case SERVICE_E_NOT_ENOUGH_DATA: + return PROPERTY_LIST_SERVICE_E_NOT_ENOUGH_DATA; + case SERVICE_E_TIMEOUT: + return PROPERTY_LIST_SERVICE_E_RECEIVE_TIMEOUT; +diff --git a/src/service.c b/src/service.c +index 57d987c..661c4f6 100644 +--- a/src/service.c ++++ b/src/service.c +@@ -47,7 +47,7 @@ static service_error_t idevice_to_service_error(idevice_error_t err) + case IDEVICE_E_SSL_ERROR: + return SERVICE_E_SSL_ERROR; + case IDEVICE_E_NOT_ENOUGH_DATA: +- return SERIVCE_E_NOT_ENOUGH_DATA; ++ return SERVICE_E_NOT_ENOUGH_DATA; + case IDEVICE_E_TIMEOUT: + return SERVICE_E_TIMEOUT; + default: +-- +2.23.0 + + +From fa1c5a9029b321adc2597bbe76920e5a7efd785b Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Sun, 16 Jun 2019 01:24:19 +0200 +Subject: [PATCH 108/151] service: Silence timeout errors + +--- + src/idevice.c | 1 - + src/service.c | 16 ++++++++-------- + 2 files changed, 8 insertions(+), 9 deletions(-) + +diff --git a/src/idevice.c b/src/idevice.c +index 5d5c950..745d784 100644 +--- a/src/idevice.c ++++ b/src/idevice.c +@@ -390,7 +390,6 @@ static idevice_error_t socket_recv_to_idevice_error(int conn_error, uint32_t len + debug_info("ERROR: received partial data %d/%d (%s)", received, len, strerror(-conn_error)); + return IDEVICE_E_NOT_ENOUGH_DATA; + case -ETIMEDOUT: +- debug_info("ERROR: received timeout (%s)", strerror(-conn_error)); + return IDEVICE_E_TIMEOUT; + default: + return IDEVICE_E_UNKNOWN_ERROR; +diff --git a/src/service.c b/src/service.c +index 661c4f6..091b599 100644 +--- a/src/service.c ++++ b/src/service.c +@@ -135,19 +135,19 @@ LIBIMOBILEDEVICE_API service_error_t service_client_free(service_client_t client + LIBIMOBILEDEVICE_API service_error_t service_send(service_client_t client, const char* data, uint32_t size, uint32_t *sent) + { + service_error_t res = SERVICE_E_UNKNOWN_ERROR; +- int bytes = 0; ++ uint32_t bytes = 0; + + if (!client || (client && !client->connection) || !data || (size == 0)) { + return SERVICE_E_INVALID_ARG; + } + + debug_info("sending %d bytes", size); +- res = idevice_to_service_error(idevice_connection_send(client->connection, data, size, (uint32_t*)&bytes)); +- if (bytes <= 0) { ++ res = idevice_to_service_error(idevice_connection_send(client->connection, data, size, &bytes)); ++ if (res != SERVICE_E_SUCCESS) { + debug_info("ERROR: sending to device failed."); + } + if (sent) { +- *sent = (uint32_t)bytes; ++ *sent = bytes; + } + + return res; +@@ -156,19 +156,19 @@ LIBIMOBILEDEVICE_API service_error_t service_send(service_client_t client, const + LIBIMOBILEDEVICE_API service_error_t service_receive_with_timeout(service_client_t client, char* data, uint32_t size, uint32_t *received, unsigned int timeout) + { + service_error_t res = SERVICE_E_UNKNOWN_ERROR; +- int bytes = 0; ++ uint32_t bytes = 0; + + if (!client || (client && !client->connection) || !data || (size == 0)) { + return SERVICE_E_INVALID_ARG; + } + +- res = idevice_to_service_error(idevice_connection_receive_timeout(client->connection, data, size, (uint32_t*)&bytes, timeout)); +- if (res != SERVICE_E_SUCCESS) { ++ res = idevice_to_service_error(idevice_connection_receive_timeout(client->connection, data, size, &bytes, timeout)); ++ if (res != SERVICE_E_SUCCESS && res != SERVICE_E_TIMEOUT) { + debug_info("could not read data"); + return res; + } + if (received) { +- *received = (uint32_t)bytes; ++ *received = bytes; + } + + return res; +-- +2.23.0 + + +From 7a0ab5f8f25b1c7f0c7313d7feda9c41c8058702 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Sun, 16 Jun 2019 01:25:12 +0200 +Subject: [PATCH 109/151] syslog_relay: Fix timeout issue introduced with + recent libusbmuxd commit ca245709 + +--- + include/libimobiledevice/syslog_relay.h | 12 +++++++----- + src/syslog_relay.c | 8 ++++++-- + 2 files changed, 13 insertions(+), 7 deletions(-) + +diff --git a/include/libimobiledevice/syslog_relay.h b/include/libimobiledevice/syslog_relay.h +index 0080b54..ea7b649 100644 +--- a/include/libimobiledevice/syslog_relay.h ++++ b/include/libimobiledevice/syslog_relay.h +@@ -34,11 +34,13 @@ extern "C" { + + /** Error Codes */ + typedef enum { +- SYSLOG_RELAY_E_SUCCESS = 0, +- SYSLOG_RELAY_E_INVALID_ARG = -1, +- SYSLOG_RELAY_E_MUX_ERROR = -2, +- SYSLOG_RELAY_E_SSL_ERROR = -3, +- SYSLOG_RELAY_E_UNKNOWN_ERROR = -256 ++ SYSLOG_RELAY_E_SUCCESS = 0, ++ SYSLOG_RELAY_E_INVALID_ARG = -1, ++ SYSLOG_RELAY_E_MUX_ERROR = -2, ++ SYSLOG_RELAY_E_SSL_ERROR = -3, ++ SYSLOG_RELAY_E_NOT_ENOUGH_DATA = -4, ++ SYSLOG_RELAY_E_TIMEOUT = -5, ++ SYSLOG_RELAY_E_UNKNOWN_ERROR = -256 + } syslog_relay_error_t; + + typedef struct syslog_relay_client_private syslog_relay_client_private; +diff --git a/src/syslog_relay.c b/src/syslog_relay.c +index 3be84e0..0d71392 100644 +--- a/src/syslog_relay.c ++++ b/src/syslog_relay.c +@@ -55,6 +55,10 @@ static syslog_relay_error_t syslog_relay_error(service_error_t err) + return SYSLOG_RELAY_E_MUX_ERROR; + case SERVICE_E_SSL_ERROR: + return SYSLOG_RELAY_E_SSL_ERROR; ++ case SERVICE_E_NOT_ENOUGH_DATA: ++ return SYSLOG_RELAY_E_NOT_ENOUGH_DATA; ++ case SERVICE_E_TIMEOUT: ++ return SYSLOG_RELAY_E_TIMEOUT; + default: + break; + } +@@ -129,7 +133,7 @@ LIBIMOBILEDEVICE_API syslog_relay_error_t syslog_relay_receive_with_timeout(sysl + } + + res = syslog_relay_error(service_receive_with_timeout(client->parent, data, size, (uint32_t*)&bytes, timeout)); +- if (bytes <= 0) { ++ if (res != SYSLOG_RELAY_E_SUCCESS && res != SYSLOG_RELAY_E_TIMEOUT && res != SYSLOG_RELAY_E_NOT_ENOUGH_DATA) { + debug_info("Could not read data, error %d", res); + } + if (received) { +@@ -153,7 +157,7 @@ void *syslog_relay_worker(void *arg) + char c; + uint32_t bytes = 0; + ret = syslog_relay_receive_with_timeout(srwt->client, &c, 1, &bytes, 100); +- if ((bytes == 0) && (ret == SYSLOG_RELAY_E_SUCCESS)) { ++ if (ret == SYSLOG_RELAY_E_TIMEOUT || ret == SYSLOG_RELAY_E_NOT_ENOUGH_DATA || ((bytes == 0) && (ret == SYSLOG_RELAY_E_SUCCESS))) { + continue; + } else if (ret < 0) { + debug_info("Connection to syslog relay interrupted"); +-- +2.23.0 + + +From ddba0b5efbcab483e80be10130c5c797f9ac8d08 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Sun, 16 Jun 2019 03:38:50 +0200 +Subject: [PATCH 110/151] notification_proxy: Make np_observe_notifications() + atomic + +Otherwise the notification callback might fire before all notifications that should be observed have been +registered. This way the callback will only be called after _all_ notifications have been registered. +--- + src/notification_proxy.c | 21 ++++++++++++++------- + 1 file changed, 14 insertions(+), 7 deletions(-) + +diff --git a/src/notification_proxy.c b/src/notification_proxy.c +index 3015ed9..cd8e64c 100644 +--- a/src/notification_proxy.c ++++ b/src/notification_proxy.c +@@ -186,13 +186,8 @@ LIBIMOBILEDEVICE_API np_error_t np_post_notification(np_client_t client, const c + return res; + } + +-LIBIMOBILEDEVICE_API np_error_t np_observe_notification( np_client_t client, const char *notification ) ++static np_error_t internal_np_observe_notification(np_client_t client, const char *notification) + { +- if (!client || !notification) { +- return NP_E_INVALID_ARG; +- } +- np_lock(client); +- + plist_t dict = plist_new_dict(); + plist_dict_set_item(dict,"Command", plist_new_string("ObserveNotification")); + plist_dict_set_item(dict,"Name", plist_new_string(notification)); +@@ -203,6 +198,16 @@ LIBIMOBILEDEVICE_API np_error_t np_observe_notification( np_client_t client, con + } + plist_free(dict); + ++ return res; ++} ++ ++LIBIMOBILEDEVICE_API np_error_t np_observe_notification( np_client_t client, const char *notification ) ++{ ++ if (!client || !notification) { ++ return NP_E_INVALID_ARG; ++ } ++ np_lock(client); ++ np_error_t res = internal_np_observe_notification(client, notification); + np_unlock(client); + return res; + } +@@ -221,13 +226,15 @@ LIBIMOBILEDEVICE_API np_error_t np_observe_notifications(np_client_t client, con + return NP_E_INVALID_ARG; + } + ++ np_lock(client); + while (notifications[i]) { +- res = np_observe_notification(client, notifications[i]); ++ res = internal_np_observe_notification(client, notifications[i]); + if (res != NP_E_SUCCESS) { + break; + } + i++; + } ++ np_unlock(client); + + return res; + } +-- +2.23.0 + + +From aa014c43a7dccd519c0c89605711906b30b98888 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Fri, 21 Jun 2019 21:30:08 +0200 +Subject: [PATCH 111/151] Converted README to markdown and updated links + +--- + README | 79 ------------------------------------------------------- + README.md | 68 +++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 68 insertions(+), 79 deletions(-) + delete mode 100644 README + create mode 100644 README.md + +diff --git a/README b/README +deleted file mode 100644 +index efc09c0..0000000 +--- a/README ++++ /dev/null +@@ -1,79 +0,0 @@ +-About +-===== +- +-A library to communicate with services of Apple iOS devices using native +-protocols. +- +-Requirements +-============ +- +-Development Packages of: +- OpenSSL or GnuTLS +- libplist +- libusbmuxd +- +-Software: +- usbmuxd +- make +- autoheader +- automake +- autoconf +- libtool +- pkg-config +- gcc or clang +- +-Optional: +- cython (Python bindings) +- doxygen (Documentation) +- +-Installation +-============ +- +-To compile run: +- ./autogen.sh +- make +- sudo make install +- +-If you require a custom prefix or other option being passed to ./configure +-you can pass them directly to ./autogen.sh like this: +- ./autogen.sh --prefix=/opt/local --enable-debug-code +- make +- sudo make install +- +-By default, OpenSSL will be used. If you prefer GnuTLS, configure with +- --disable-openssl like this: +- ./autogen.sh --disable-openssl +- +-Who/What/Where? +-=============== +- +-Home: +- http://www.libimobiledevice.org/ +- +-Code: +- git clone http://git.libimobiledevice.org/libimobiledevice.git +- +-Code (Mirror): +- git clone https://github.com/libimobiledevice/libimobiledevice.git +- +-Tickets: +- https://github.com/libimobiledevice/libimobiledevice/issues +- +-Mailing List: +- http://lists.libimobiledevice.org/mailman/listinfo/libimobiledevice-devel +- +-IRC: +- irc://irc.freenode.net#libimobiledevice +- +-Twitter: +- https://twitter.com/libimobiledev +- +-Credits +-======= +- +-Apple, iPhone, iPod, and iPod Touch are trademarks of Apple Inc. +-libimobiledevice is an independent software library and has not been +-authorized, sponsored, or otherwise approved by Apple Inc. +- +-README Updated on: +- 2017-04-28 +diff --git a/README.md b/README.md +new file mode 100644 +index 0000000..3f9493c +--- /dev/null ++++ b/README.md +@@ -0,0 +1,68 @@ ++# libimobiledevice ++ ++## About ++ ++A library to communicate with services of Apple iOS devices using native ++protocols. ++ ++## Requirements ++ ++Development Packages of: ++* OpenSSL or GnuTLS ++* libplist ++* libusbmuxd ++ ++Software: ++* usbmuxd (OSS or Apple's version) ++* make ++* autoheader ++* automake ++* autoconf ++* libtool ++* pkg-config ++* gcc or clang ++ ++Optional: ++* cython (Python bindings) ++* doxygen (Documentation) ++ ++## Installation ++ ++To compile run: ++```bash ++./autogen.sh ++make ++sudo make install ++``` ++ ++If you require a custom prefix or other option being passed to `./configure` ++you can pass them directly to `./autogen.sh` like this: ++```bash ++./autogen.sh --prefix=/opt/local --enable-debug-code ++make ++sudo make install ++``` ++ ++By default, OpenSSL will be used. If you prefer GnuTLS, configure with ++`--disable-openssl` like this: ++```bash ++./autogen.sh --disable-openssl ++``` ++ ++## Who/What/Where? ++ ++* Home: https://www.libimobiledevice.org/ ++* Code: `git clone https://git.libimobiledevice.org/libimobiledevice.git` ++* Code (Mirror): `git clone https://github.com/libimobiledevice/libimobiledevice.git` ++* Tickets: https://github.com/libimobiledevice/libimobiledevice/issues ++* Mailing List: https://lists.libimobiledevice.org/mailman/listinfo/libimobiledevice-devel ++* IRC: irc://irc.freenode.net#libimobiledevice ++* Twitter: https://twitter.com/libimobiledev ++ ++## Credits ++ ++Apple, iPhone, iPod, and iPod Touch are trademarks of Apple Inc. ++libimobiledevice is an independent software library and has not been ++authorized, sponsored, or otherwise approved by Apple Inc. ++ ++README Updated on: 2019-06-21 +-- +2.23.0 + + +From 1d4ac48da49809e3c38574b711697cbb2ee0d773 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Fri, 21 Jun 2019 21:31:21 +0200 +Subject: [PATCH 112/151] idevicebackup2: Handle errors when receiving files + and report back to device + +--- + tools/idevicebackup2.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/tools/idevicebackup2.c b/tools/idevicebackup2.c +index 1e6ddf7..0aae36e 100644 +--- a/tools/idevicebackup2.c ++++ b/tools/idevicebackup2.c +@@ -1004,6 +1004,8 @@ static int mb2_handle_receive_files(mobilebackup2_client_t mobilebackup2, plist_ + plist_t node = NULL; + FILE *f = NULL; + unsigned int file_count = 0; ++ int errcode = 0; ++ char *errdesc = NULL; + + if (!message || (plist_get_node_type(message) != PLIST_ARRAY) || plist_array_get_size(message) < 4 || !backup_dir) return 0; + +@@ -1105,7 +1107,10 @@ static int mb2_handle_receive_files(mobilebackup2_client_t mobilebackup2, plist_ + fclose(f); + file_count++; + } else { +- printf("Error opening '%s' for writing: %s\n", bname, strerror(errno)); ++ errcode = errno_to_device_error(errno); ++ errdesc = strerror(errno); ++ printf("Error opening '%s' for writing: %s\n", bname, errdesc); ++ break; + } + if (nlen == 0) { + break; +@@ -1144,9 +1149,8 @@ static int mb2_handle_receive_files(mobilebackup2_client_t mobilebackup2, plist_ + if (dname != NULL) + free(dname); + +- // TODO error handling?! + plist_t empty_plist = plist_new_dict(); +- mobilebackup2_send_status_response(mobilebackup2, 0, NULL, empty_plist); ++ mobilebackup2_send_status_response(mobilebackup2, errcode, errdesc, empty_plist); + plist_free(empty_plist); + + return file_count; +-- +2.23.0 + + +From b3eaf9ce6a852c2000ce443e851ef9fc36a4d331 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Fri, 21 Jun 2019 21:44:19 +0200 +Subject: [PATCH 113/151] Use OPENSSL_THREADID_* API for OpenSSL >= 1.0.0 && < + 1.1.0 + +--- + src/idevice.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/src/idevice.c b/src/idevice.c +index 745d784..8c81576 100644 +--- a/src/idevice.c ++++ b/src/idevice.c +@@ -79,12 +79,19 @@ static void locking_function(int mode, int n, const char* file, int line) + mutex_unlock(&mutex_buf[n]); + } + ++#if OPENSSL_VERSION_NUMBER < 0x10000000L + static unsigned long id_function(void) + { + return ((unsigned long)THREAD_ID); + } ++#else ++static void id_function(CRYPTO_THREADID *thread) ++{ ++ CRYPTO_THREADID_set_numeric(thread, (unsigned long)THREAD_ID); ++} + #endif + #endif ++#endif /* HAVE_OPENSSL */ + + static void internal_idevice_init(void) + { +@@ -99,7 +106,11 @@ static void internal_idevice_init(void) + for (i = 0; i < CRYPTO_num_locks(); i++) + mutex_init(&mutex_buf[i]); + ++#if OPENSSL_VERSION_NUMBER < 0x10000000L + CRYPTO_set_id_callback(id_function); ++#else ++ CRYPTO_THREADID_set_callback(id_function); ++#endif + CRYPTO_set_locking_callback(locking_function); + #endif + #else +@@ -113,7 +124,11 @@ static void internal_idevice_deinit(void) + #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) + int i; + if (mutex_buf) { ++#if OPENSSL_VERSION_NUMBER < 0x10000000L + CRYPTO_set_id_callback(NULL); ++#else ++ CRYPTO_THREADID_set_callback(NULL); ++#endif + CRYPTO_set_locking_callback(NULL); + for (i = 0; i < CRYPTO_num_locks(); i++) + mutex_destroy(&mutex_buf[i]); +-- +2.23.0 + + +From e8dac8e231b72bfec56e32873d8572b673c1adbc Mon Sep 17 00:00:00 2001 +From: Rosen Penev +Date: Sat, 22 Jun 2019 02:19:18 +0200 +Subject: [PATCH 114/151] Make sure to not use deprecated API when compiling + with OpenSSL >= 1.1 + +There are several missing headers as well as deprecated functions for +which compatibility was added as needed. +--- + common/userpref.c | 18 ++++++++++++------ + src/idevice.c | 8 +++++++- + 2 files changed, 19 insertions(+), 7 deletions(-) + +diff --git a/common/userpref.c b/common/userpref.c +index b985285..a5aa7cb 100644 +--- a/common/userpref.c ++++ b/common/userpref.c +@@ -37,10 +37,16 @@ + #include + #include + #ifdef HAVE_OPENSSL ++#include + #include + #include + #include + #include ++#if OPENSSL_VERSION_NUMBER < 0x1010000fL || \ ++ (defined(LIBRESSL_VERSION_NUMBER) && (LIBRESSL_VERSION_NUMBER < 0x20700000L)) ++#define X509_set1_notBefore X509_set_notBefore ++#define X509_set1_notAfter X509_set_notAfter ++#endif + #else + #include + #include +@@ -420,9 +426,9 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da + /* set key validity */ + ASN1_TIME* asn1time = ASN1_TIME_new(); + ASN1_TIME_set(asn1time, time(NULL)); +- X509_set_notBefore(root_cert, asn1time); ++ X509_set1_notBefore(root_cert, asn1time); + ASN1_TIME_set(asn1time, time(NULL) + (60 * 60 * 24 * 365 * 10)); +- X509_set_notAfter(root_cert, asn1time); ++ X509_set1_notAfter(root_cert, asn1time); + ASN1_TIME_free(asn1time); + + /* use root public key for root cert */ +@@ -453,9 +459,9 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da + /* set key validity */ + ASN1_TIME* asn1time = ASN1_TIME_new(); + ASN1_TIME_set(asn1time, time(NULL)); +- X509_set_notBefore(host_cert, asn1time); ++ X509_set1_notBefore(host_cert, asn1time); + ASN1_TIME_set(asn1time, time(NULL) + (60 * 60 * 24 * 365 * 10)); +- X509_set_notAfter(host_cert, asn1time); ++ X509_set1_notAfter(host_cert, asn1time); + ASN1_TIME_free(asn1time); + + /* use host public key for host cert */ +@@ -533,9 +539,9 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da + + ASN1_TIME* asn1time = ASN1_TIME_new(); + ASN1_TIME_set(asn1time, time(NULL)); +- X509_set_notBefore(dev_cert, asn1time); ++ X509_set1_notBefore(dev_cert, asn1time); + ASN1_TIME_set(asn1time, time(NULL) + (60 * 60 * 24 * 365 * 10)); +- X509_set_notAfter(dev_cert, asn1time); ++ X509_set1_notAfter(dev_cert, asn1time); + ASN1_TIME_free(asn1time); + + EVP_PKEY* pkey = EVP_PKEY_new(); +diff --git a/src/idevice.c b/src/idevice.c +index 8c81576..02d34cc 100644 +--- a/src/idevice.c ++++ b/src/idevice.c +@@ -36,6 +36,7 @@ + #include + #ifdef HAVE_OPENSSL + #include ++#include + #include + #else + #include +@@ -49,6 +50,11 @@ + + #ifdef HAVE_OPENSSL + ++#if OPENSSL_VERSION_NUMBER < 0x10100000L || \ ++ (defined(LIBRESSL_VERSION_NUMBER) && (LIBRESSL_VERSION_NUMBER < 0x20020000L)) ++#define TLS_method TLSv1_method ++#endif ++ + #if OPENSSL_VERSION_NUMBER < 0x10002000L || defined(LIBRESSL_VERSION_NUMBER) + static void SSL_COMP_free_compression_methods(void) + { +@@ -771,7 +777,7 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_enable_ssl(idevice_conne + } + BIO_set_fd(ssl_bio, (int)(long)connection->data, BIO_NOCLOSE); + +- SSL_CTX *ssl_ctx = SSL_CTX_new(TLSv1_method()); ++ SSL_CTX *ssl_ctx = SSL_CTX_new(TLS_method()); + if (ssl_ctx == NULL) { + debug_info("ERROR: Could not create SSL context."); + BIO_free(ssl_bio); +-- +2.23.0 + + +From b8df28038f3ca8a3a8be6569cea251d2506c3171 Mon Sep 17 00:00:00 2001 +From: Rosen Penev +Date: Wed, 27 Mar 2019 21:27:18 -0700 +Subject: [PATCH 115/151] configure.ac: Remove largefile hackery + +It requires a program to be ran, which cannot be done when cross compiling. +AC_SYS_LARGEFILE seems to be enough to implement largefile checking. +--- + configure.ac | 24 ------------------------ + 1 file changed, 24 deletions(-) + +diff --git a/configure.ac b/configure.ac +index a2a5b12..41fabbc 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -181,30 +181,6 @@ esac + + # check for large file support + AC_SYS_LARGEFILE +-LFS_CFLAGS='' +-if test "$enable_largefile" != no; then +- if test "$ac_cv_sys_file_offset_bits" != 'no'; then +- LFS_CFLAGS="$LFS_CFLAGS -D_FILE_OFFSET_BITS=$ac_cv_sys_file_offset_bits" +- else +- AC_MSG_CHECKING(for native large file support) +- AC_RUN_IFELSE([AC_LANG_SOURCE([#include +- int main (int argc, char **argv) +- { +- exit(!(sizeof(off_t) == 8)); +- }])], +- [ac_cv_sys_file_offset_bits=64; AC_DEFINE(_FILE_OFFSET_BITS,64) +- AC_MSG_RESULT(yes)], +- [AC_MSG_RESULT(no)]) +- fi +- if test "$ac_cv_sys_large_files" != 'no'; then +- LFS_CFLAGS="$LFS_CFLAGS -D_LARGE_FILES=1" +- fi +- AC_FUNC_FSEEKO +- if test "$ac_cv_sys_largefile_source" != 'no'; then +- LFS_CFLAGS="$LFS_CFLAGS -D_LARGEFILE_SOURCE=1" +- fi +-fi +-AC_SUBST(LFS_CFLAGS) + + m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])]) + +-- +2.23.0 + + +From 41ce2454b7f0b4a679070ea377545ba34f70095f Mon Sep 17 00:00:00 2001 +From: Yves-Alexis Perez +Date: Mon, 8 Oct 2018 13:39:31 +0200 +Subject: [PATCH 116/151] replace all occurrences of occured by occurred + +Do it in all comments and errors messages +--- + include/libimobiledevice/house_arrest.h | 6 ++--- + include/libimobiledevice/installation_proxy.h | 26 +++++++++---------- + include/libimobiledevice/libimobiledevice.h | 8 +++--- + include/libimobiledevice/mobilebackup2.h | 2 +- + .../libimobiledevice/property_list_service.h | 2 +- + include/libimobiledevice/screenshotr.h | 2 +- + include/libimobiledevice/service.h | 2 +- + src/diagnostics_relay.c | 2 +- + src/installation_proxy.c | 6 ++--- + src/lockdown.c | 2 +- + src/misagent.c | 2 +- + src/notification_proxy.c | 4 +-- + src/restore.c | 2 +- + tools/idevicebackup.c | 4 +-- + tools/idevicebackup2.c | 4 +-- + 15 files changed, 37 insertions(+), 37 deletions(-) + +diff --git a/include/libimobiledevice/house_arrest.h b/include/libimobiledevice/house_arrest.h +index 31b6401..5a42838 100644 +--- a/include/libimobiledevice/house_arrest.h ++++ b/include/libimobiledevice/house_arrest.h +@@ -109,7 +109,7 @@ house_arrest_error_t house_arrest_client_free(house_arrest_client_t client); + * HOUSE_ARREST_E_INVALID_ARG if client or dict is invalid, + * HOUSE_ARREST_E_PLIST_ERROR if dict is not a plist of type PLIST_DICT, + * HOUSE_ARREST_E_INVALID_MODE if the client is not in the correct mode, +- * or HOUSE_ARREST_E_CONN_FAILED if a connection error occured. ++ * or HOUSE_ARREST_E_CONN_FAILED if a connection error occurred. + */ + house_arrest_error_t house_arrest_send_request(house_arrest_client_t client, plist_t dict); + +@@ -130,7 +130,7 @@ house_arrest_error_t house_arrest_send_request(house_arrest_client_t client, pli + * @return HOUSE_ARREST_E_SUCCESS if the command was successfully sent, + * HOUSE_ARREST_E_INVALID_ARG if client, command, or appid is invalid, + * HOUSE_ARREST_E_INVALID_MODE if the client is not in the correct mode, +- * or HOUSE_ARREST_E_CONN_FAILED if a connection error occured. ++ * or HOUSE_ARREST_E_CONN_FAILED if a connection error occurred. + */ + house_arrest_error_t house_arrest_send_command(house_arrest_client_t client, const char *command, const char *appid); + +@@ -146,7 +146,7 @@ house_arrest_error_t house_arrest_send_command(house_arrest_client_t client, con + * @return HOUSE_ARREST_E_SUCCESS if a result plist was retrieved, + * HOUSE_ARREST_E_INVALID_ARG if client is invalid, + * HOUSE_ARREST_E_INVALID_MODE if the client is not in the correct mode, +- * or HOUSE_ARREST_E_CONN_FAILED if a connection error occured. ++ * or HOUSE_ARREST_E_CONN_FAILED if a connection error occurred. + */ + house_arrest_error_t house_arrest_get_result(house_arrest_client_t client, plist_t *dict); + +diff --git a/include/libimobiledevice/installation_proxy.h b/include/libimobiledevice/installation_proxy.h +index bc23f9d..1ff82dc 100644 +--- a/include/libimobiledevice/installation_proxy.h ++++ b/include/libimobiledevice/installation_proxy.h +@@ -124,7 +124,7 @@ typedef void (*instproxy_status_cb_t) (plist_t command, plist_t status, void *us + * instproxy_client_t upon successful return. + * + * @return INSTPROXY_E_SUCCESS on success, or an INSTPROXY_E_* error value +- * when an error occured. ++ * when an error occurred. + */ + instproxy_error_t instproxy_client_new(idevice_t device, lockdownd_service_descriptor_t service, instproxy_client_t *client); + +@@ -168,7 +168,7 @@ instproxy_error_t instproxy_client_free(instproxy_client_t client); + * of PLIST_DICT holding information about the applications found. + * + * @return INSTPROXY_E_SUCCESS on success or an INSTPROXY_E_* error value if +- * an error occured. ++ * an error occurred. + */ + instproxy_error_t instproxy_browse(instproxy_client_t client, plist_t client_options, plist_t *result); + +@@ -187,7 +187,7 @@ instproxy_error_t instproxy_browse(instproxy_client_t client, plist_t client_opt + * @param user_data Callback data passed to status_cb. + * + * @return INSTPROXY_E_SUCCESS on success or an INSTPROXY_E_* error value if +- * an error occured. ++ * an error occurred. + */ + instproxy_error_t instproxy_browse_with_callback(instproxy_client_t client, plist_t client_options, instproxy_status_cb_t status_cb, void *user_data); + +@@ -203,7 +203,7 @@ instproxy_error_t instproxy_browse_with_callback(instproxy_client_t client, plis + * holding requested information about the application or NULL on errors. + * + * @return INSTPROXY_E_SUCCESS on success or an INSTPROXY_E_* error value if +- * an error occured. ++ * an error occurred. + */ + instproxy_error_t instproxy_lookup(instproxy_client_t client, const char** appids, plist_t client_options, plist_t *result); + +@@ -224,7 +224,7 @@ instproxy_error_t instproxy_lookup(instproxy_client_t client, const char** appid + * @param user_data Callback data passed to status_cb. + * + * @return INSTPROXY_E_SUCCESS on success or an INSTPROXY_E_* error value if +- * an error occured. ++ * an error occurred. + * + * @note If a callback function is given (async mode), this function returns + * INSTPROXY_E_SUCCESS immediately if the status updater thread has been +@@ -252,7 +252,7 @@ instproxy_error_t instproxy_install(instproxy_client_t client, const char *pkg_p + * @param user_data Callback data passed to status_cb. + * + * @return INSTPROXY_E_SUCCESS on success or an INSTPROXY_E_* error value if +- * an error occured. ++ * an error occurred. + * + * @note If a callback function is given (async mode), this function returns + * INSTPROXY_E_SUCCESS immediately if the status updater thread has been +@@ -273,7 +273,7 @@ instproxy_error_t instproxy_upgrade(instproxy_client_t client, const char *pkg_p + * @param user_data Callback data passed to status_cb. + * + * @return INSTPROXY_E_SUCCESS on success or an INSTPROXY_E_* error value if +- * an error occured. ++ * an error occurred. + * + * @note If a callback function is given (async mode), this function returns + * INSTPROXY_E_SUCCESS immediately if the status updater thread has been +@@ -294,7 +294,7 @@ instproxy_error_t instproxy_uninstall(instproxy_client_t client, const char *app + * holding information about the archived applications found. + * + * @return INSTPROXY_E_SUCCESS on success or an INSTPROXY_E_* error value if +- * an error occured. ++ * an error occurred. + */ + instproxy_error_t instproxy_lookup_archives(instproxy_client_t client, plist_t client_options, plist_t *result); + +@@ -315,7 +315,7 @@ instproxy_error_t instproxy_lookup_archives(instproxy_client_t client, plist_t c + * @param user_data Callback data passed to status_cb. + * + * @return INSTPROXY_E_SUCCESS on success or an INSTPROXY_E_* error value if +- * an error occured. ++ * an error occurred. + * + * @note If a callback function is given (async mode), this function returns + * INSTPROXY_E_SUCCESS immediately if the status updater thread has been +@@ -339,7 +339,7 @@ instproxy_error_t instproxy_archive(instproxy_client_t client, const char *appid + * @param user_data Callback data passed to status_cb. + * + * @return INSTPROXY_E_SUCCESS on success or an INSTPROXY_E_* error value if +- * an error occured. ++ * an error occurred. + * + * @note If a callback function is given (async mode), this function returns + * INSTPROXY_E_SUCCESS immediately if the status updater thread has been +@@ -362,7 +362,7 @@ instproxy_error_t instproxy_restore(instproxy_client_t client, const char *appid + * @param user_data Callback data passed to status_cb. + * + * @return INSTPROXY_E_SUCCESS on success or an INSTPROXY_E_* error value if +- * an error occured. ++ * an error occurred. + * + * @note If a callback function is given (async mode), this function returns + * INSTPROXY_E_SUCCESS immediately if the status updater thread has been +@@ -383,7 +383,7 @@ instproxy_error_t instproxy_remove_archive(instproxy_client_t client, const char + * holding information if the capabilities matched or NULL on errors. + * + * @return INSTPROXY_E_SUCCESS on success or an INSTPROXY_E_* error value if +- * an error occured. ++ * an error occurred. + */ + instproxy_error_t instproxy_check_capabilities_match(instproxy_client_t client, const char** capabilities, plist_t client_options, plist_t *result); + +@@ -493,7 +493,7 @@ void instproxy_client_options_free(plist_t client_options); + * + * @return INSTPROXY_E_SUCCESS on success, INSTPROXY_E_OP_FAILED if + * the path could not be determined or an INSTPROXY_E_* error +- * value if an error occured. ++ * value if an error occurred. + */ + instproxy_error_t instproxy_client_get_path_for_bundle_identifier(instproxy_client_t client, const char* bundle_id, char** path); + +diff --git a/include/libimobiledevice/libimobiledevice.h b/include/libimobiledevice/libimobiledevice.h +index 729bc89..8f8589d 100644 +--- a/include/libimobiledevice/libimobiledevice.h ++++ b/include/libimobiledevice/libimobiledevice.h +@@ -60,7 +60,7 @@ enum idevice_event_type { + }; + + /* event data structure */ +-/** Provides information about the occured event. */ ++/** Provides information about the occurred event. */ + typedef struct { + enum idevice_event_type event; /**< The event type. */ + const char *udid; /**< The device unique id. */ +@@ -88,7 +88,7 @@ void idevice_set_debug_level(int level); + * @param user_data Application-specific data passed as parameter + * to the registered callback function. + * +- * @return IDEVICE_E_SUCCESS on success or an error value when an error occured. ++ * @return IDEVICE_E_SUCCESS on success or an error value when an error occurred. + */ + idevice_error_t idevice_event_subscribe(idevice_event_cb_t callback, void *user_data); + +@@ -96,7 +96,7 @@ idevice_error_t idevice_event_subscribe(idevice_event_cb_t callback, void *user_ + * Release the event callback function that has been registered with + * idevice_event_subscribe(). + * +- * @return IDEVICE_E_SUCCESS on success or an error value when an error occured. ++ * @return IDEVICE_E_SUCCESS on success or an error value when an error occurred. + */ + idevice_error_t idevice_event_unsubscribe(void); + +@@ -109,7 +109,7 @@ idevice_error_t idevice_event_unsubscribe(void); + * This list is terminated by a NULL pointer. + * @param count Number of devices found. + * +- * @return IDEVICE_E_SUCCESS on success or an error value when an error occured. ++ * @return IDEVICE_E_SUCCESS on success or an error value when an error occurred. + */ + idevice_error_t idevice_get_device_list(char ***devices, int *count); + +diff --git a/include/libimobiledevice/mobilebackup2.h b/include/libimobiledevice/mobilebackup2.h +index 1f20d40..0c42334 100644 +--- a/include/libimobiledevice/mobilebackup2.h ++++ b/include/libimobiledevice/mobilebackup2.h +@@ -146,7 +146,7 @@ mobilebackup2_error_t mobilebackup2_send_raw(mobilebackup2_client_t client, cons + * Receive binary from the device. + * + * @note This function returns MOBILEBACKUP2_E_SUCCESS even if no data +- * has been received (unless a communication error occured). ++ * has been received (unless a communication error occurred). + * The fourth parameter is required and must be checked to know how + * many bytes were actually received. + * +diff --git a/include/libimobiledevice/property_list_service.h b/include/libimobiledevice/property_list_service.h +index aca966d..031d6f8 100644 +--- a/include/libimobiledevice/property_list_service.h ++++ b/include/libimobiledevice/property_list_service.h +@@ -68,7 +68,7 @@ property_list_service_error_t property_list_service_client_new(idevice_t device, + * + * @return PROPERTY_LIST_SERVICE_E_SUCCESS on success, + * PROPERTY_LIST_SERVICE_E_INVALID_ARG when client is invalid, or a +- * PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR when another error occured. ++ * PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR when another error occurred. + */ + property_list_service_error_t property_list_service_client_free(property_list_service_client_t client); + +diff --git a/include/libimobiledevice/screenshotr.h b/include/libimobiledevice/screenshotr.h +index 0d44255..c12646b 100644 +--- a/include/libimobiledevice/screenshotr.h ++++ b/include/libimobiledevice/screenshotr.h +@@ -104,7 +104,7 @@ screenshotr_error_t screenshotr_client_free(screenshotr_client_t client); + * + * @return SCREENSHOTR_E_SUCCESS on success, SCREENSHOTR_E_INVALID_ARG if + * one or more parameters are invalid, or another error code if an +- * error occured. ++ * error occurred. + */ + screenshotr_error_t screenshotr_take_screenshot(screenshotr_client_t client, char **imgdata, uint64_t *imgsize); + +diff --git a/include/libimobiledevice/service.h b/include/libimobiledevice/service.h +index facf03b..84c5092 100644 +--- a/include/libimobiledevice/service.h ++++ b/include/libimobiledevice/service.h +@@ -87,7 +87,7 @@ service_error_t service_client_factory_start_service(idevice_t device, const cha + * + * @return SERVICE_E_SUCCESS on success, + * SERVICE_E_INVALID_ARG when client is invalid, or a +- * SERVICE_E_UNKNOWN_ERROR when another error occured. ++ * SERVICE_E_UNKNOWN_ERROR when another error occurred. + */ + service_error_t service_client_free(service_client_t client); + +diff --git a/src/diagnostics_relay.c b/src/diagnostics_relay.c +index 79e041e..0834700 100644 +--- a/src/diagnostics_relay.c ++++ b/src/diagnostics_relay.c +@@ -36,7 +36,7 @@ + * + * @return RESULT_SUCCESS when the result is 'Success', + * RESULT_FAILURE when the result is 'Failure', +- * or a negative value if an error occured during evaluation. ++ * or a negative value if an error occurred during evaluation. + */ + static int diagnostics_relay_check_result(plist_t dict) + { +diff --git a/src/installation_proxy.c b/src/installation_proxy.c +index 24044aa..7c2d336 100644 +--- a/src/installation_proxy.c ++++ b/src/installation_proxy.c +@@ -286,7 +286,7 @@ LIBIMOBILEDEVICE_API instproxy_error_t instproxy_client_free(instproxy_client_t + * @param package_path The installation package path or NULL if not required. + * + * @return INSTPROXY_E_SUCCESS on success or an INSTPROXY_E_* error value if +- * an error occured. ++ * an error occurred. + */ + static instproxy_error_t instproxy_send_command(instproxy_client_t client, plist_t command) + { +@@ -460,7 +460,7 @@ static void* instproxy_receive_status_loop_thread(void* arg) + * + * @return INSTPROXY_E_SUCCESS when the thread was created (async mode), or + * when the command completed successfully (sync). +- * An INSTPROXY_E_* error value is returned if an error occured. ++ * An INSTPROXY_E_* error value is returned if an error occurred. + */ + static instproxy_error_t instproxy_receive_status_loop_with_callback(instproxy_client_t client, plist_t command, instproxy_command_type_t async, instproxy_status_cb_t status_cb, void *user_data) + { +@@ -505,7 +505,7 @@ static instproxy_error_t instproxy_receive_status_loop_with_callback(instproxy_c + * @param user_data Callback data passed to status_cb. + * + * @return INSTPROXY_E_SUCCESS on success or an INSTPROXY_E_* error value if +- * an error occured. ++ * an error occurred. + */ + static instproxy_error_t instproxy_perform_command(instproxy_client_t client, plist_t command, instproxy_command_type_t async, instproxy_status_cb_t status_cb, void *user_data) + { +diff --git a/src/lockdown.c b/src/lockdown.c +index 1a162ed..23f2782 100644 +--- a/src/lockdown.c ++++ b/src/lockdown.c +@@ -219,7 +219,7 @@ static lockdownd_error_t lockdown_check_result(plist_t dict, const char *query_m + ret = lockdownd_strtoerr(err_value); + free(err_value); + } else { +- debug_info("ERROR: unknown error occured"); ++ debug_info("ERROR: unknown error occurred"); + } + } + return ret; +diff --git a/src/misagent.c b/src/misagent.c +index 095edba..91b8acb 100644 +--- a/src/misagent.c ++++ b/src/misagent.c +@@ -57,7 +57,7 @@ static misagent_error_t misagent_error(property_list_service_error_t err) + + /** + * Checks the response from misagent to determine if the operation +- * was successful or an error occured. Internally used only. ++ * was successful or an error occurred. Internally used only. + * + * @param response a PLIST_DICT received from device's misagent + * @param status_code pointer to an int that will be set to the status code +diff --git a/src/notification_proxy.c b/src/notification_proxy.c +index cd8e64c..eea01ca 100644 +--- a/src/notification_proxy.c ++++ b/src/notification_proxy.c +@@ -247,7 +247,7 @@ LIBIMOBILEDEVICE_API np_error_t np_observe_notifications(np_client_t client, con + * with the notification that has been received. + * + * @return 0 if a notification has been received or nothing has been received, +- * or a negative value if an error occured. ++ * or a negative value if an error occurred. + * + * @note You probably want to check out np_set_notify_callback + * @see np_set_notify_callback +@@ -267,7 +267,7 @@ static int np_get_notification(np_client_t client, char **notification) + debug_info("NotificationProxy: no notification received!"); + res = 0; + } else if (perr != PROPERTY_LIST_SERVICE_E_SUCCESS) { +- debug_info("NotificationProxy: error %d occured!", perr); ++ debug_info("NotificationProxy: error %d occurred!", perr); + res = perr; + } + if (dict) { +diff --git a/src/restore.c b/src/restore.c +index 4b578c2..6571a2f 100644 +--- a/src/restore.c ++++ b/src/restore.c +@@ -41,7 +41,7 @@ + * + * @return RESULT_SUCCESS when the result is 'Success', + * RESULT_FAILURE when the result is 'Failure', +- * or a negative value if an error occured during evaluation. ++ * or a negative value if an error occurred during evaluation. + */ + static int restored_check_result(plist_t dict) + { +diff --git a/tools/idevicebackup.c b/tools/idevicebackup.c +index cd69bcc..de08295 100644 +--- a/tools/idevicebackup.c ++++ b/tools/idevicebackup.c +@@ -995,7 +995,7 @@ int main(int argc, char *argv[]) + } else if (err == MOBILEBACKUP_E_REPLY_NOT_OK) { + printf("ERROR: Could not start backup process: device refused to start the backup process.\n"); + } else { +- printf("ERROR: Could not start backup process: unspecified error occured\n"); ++ printf("ERROR: Could not start backup process: unspecified error occurred\n"); + } + break; + } +@@ -1342,7 +1342,7 @@ files_out: + } else if (err == MOBILEBACKUP_E_REPLY_NOT_OK) { + printf("ERROR: Could not start restore process: device refused to start the restore process.\n"); + } else { +- printf("ERROR: Could not start restore process: unspecified error occured (%d)\n", err); ++ printf("ERROR: Could not start restore process: unspecified error occurred (%d)\n", err); + } + plist_free(backup_data); + break; +diff --git a/tools/idevicebackup2.c b/tools/idevicebackup2.c +index 0aae36e..58fda8d 100644 +--- a/tools/idevicebackup2.c ++++ b/tools/idevicebackup2.c +@@ -1954,7 +1954,7 @@ checkpoint: + } else if (err == MOBILEBACKUP2_E_REPLY_NOT_OK) { + printf("ERROR: Could not start backup process: device refused to start the backup process.\n"); + } else { +- printf("ERROR: Could not start backup process: unspecified error occured\n"); ++ printf("ERROR: Could not start backup process: unspecified error occurred\n"); + } + cmd = CMD_LEAVE; + } +@@ -2012,7 +2012,7 @@ checkpoint: + } else if (err == MOBILEBACKUP2_E_REPLY_NOT_OK) { + printf("ERROR: Could not start restore process: device refused to start the restore process.\n"); + } else { +- printf("ERROR: Could not start restore process: unspecified error occured\n"); ++ printf("ERROR: Could not start restore process: unspecified error occurred\n"); + } + cmd = CMD_LEAVE; + } +-- +2.23.0 + + +From 8591317222dbb41679f2657846fa359e76556ffe Mon Sep 17 00:00:00 2001 +From: Yves-Alexis Perez +Date: Mon, 8 Oct 2018 13:41:09 +0200 +Subject: [PATCH 117/151] Replace all occurrences of seperated by separated + +Both in idevicediagnostics man page and in an error message +--- + docs/idevicediagnostics.1 | 2 +- + tools/idevicediagnostics.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/docs/idevicediagnostics.1 b/docs/idevicediagnostics.1 +index 8a9b947..d652f39 100644 +--- a/docs/idevicediagnostics.1 ++++ b/docs/idevicediagnostics.1 +@@ -32,7 +32,7 @@ print diagnostics information from device optionally by TYPE. This includes + .TP + .B mobilegestalt KEY [...] + print values of mobilegestalt keys passed as arguments after the command and +-seperated by a space. ++separated by a space. + .TP + .B ioreg [PLANE] + print IORegistry of device, optionally by PLANE like "IODeviceTree", "IOPower" +diff --git a/tools/idevicediagnostics.c b/tools/idevicediagnostics.c +index 8c32854..08e7c5e 100644 +--- a/tools/idevicediagnostics.c ++++ b/tools/idevicediagnostics.c +@@ -310,7 +310,7 @@ void print_usage(int argc, char **argv) + printf("Use diagnostics interface of a device running iOS 4 or later.\n\n"); + printf(" Where COMMAND is one of:\n"); + printf(" diagnostics [TYPE]\t\tprint diagnostics information from device by TYPE (All, WiFi, GasGauge, NAND)\n"); +- printf(" mobilegestalt KEY [...]\tprint mobilegestalt keys passed as arguments seperated by a space.\n"); ++ printf(" mobilegestalt KEY [...]\tprint mobilegestalt keys passed as arguments separated by a space.\n"); + printf(" ioreg [PLANE]\t\t\tprint IORegistry of device, optionally by PLANE (IODeviceTree, IOPower, IOService) (iOS 5+ only)\n"); + printf(" ioregentry [KEY]\t\tprint IORegistry entry of device (AppleARMPMUCharger, ASPStorage, ...) (iOS 5+ only)\n"); + printf(" shutdown\t\t\tshutdown device\n"); +-- +2.23.0 + + +From bc508e4276d006244a10dc3cfda9526de0a4d070 Mon Sep 17 00:00:00 2001 +From: Yves-Alexis Perez +Date: Mon, 8 Oct 2018 13:42:02 +0200 +Subject: [PATCH 118/151] Fix other typos in idevicediagnostics manpage + +--- + docs/idevicediagnostics.1 | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/docs/idevicediagnostics.1 b/docs/idevicediagnostics.1 +index d652f39..3230310 100644 +--- a/docs/idevicediagnostics.1 ++++ b/docs/idevicediagnostics.1 +@@ -7,7 +7,7 @@ idevicediagnostics \- Interact with the diagnostics interface of a device. + + .SH DESCRIPTION + +-Interact with the diagnostics interface of a device which allows to retrive ++Interact with the diagnostics interface of a device which allows one to retrieve + all kinds of information including diagnostics data, mobilegestalt data, remote + access to the IORegistry and certain commands like restart, shutdown and sleep. + Only available for iOS 4 and later. Accessing IORegistry is only supported on +-- +2.23.0 + + +From 78d116c8b93e460afd28436d38275c03d7dd1f32 Mon Sep 17 00:00:00 2001 +From: Yves-Alexis Perez +Date: Mon, 8 Oct 2018 13:43:32 +0200 +Subject: [PATCH 119/151] Fix a typo in ideviceprovision error message + +--- + tools/ideviceprovision.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/ideviceprovision.c b/tools/ideviceprovision.c +index f91ce4f..52efdeb 100644 +--- a/tools/ideviceprovision.c ++++ b/tools/ideviceprovision.c +@@ -56,7 +56,7 @@ static void print_usage(int argc, char **argv) + printf(" \tstores them into the existing directory specified by PATH.\n"); + printf(" \tThe files will be stored as UUID.mobileprovision\n"); + printf(" copy UUID PATH Retrieves the provisioning profile identified by UUID\n"); +- printf(" \tfrom the device and stores it into the exisiting directory\n"); ++ printf(" \tfrom the device and stores it into the existing directory\n"); + printf(" \tspecified by PATH. The file will be stored as UUID.mobileprovision.\n"); + printf(" remove UUID\tRemoves the provisioning profile identified by UUID.\n"); + printf(" remove-all\tRemoves all installed provisioning profiles.\n"); +-- +2.23.0 + + +From 8510a9b290bc92993d2ae57a965b7f36325e1aa9 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Tue, 25 Jun 2019 15:24:37 +0200 +Subject: [PATCH 120/151] idevicecrashreport: zero-fill full struct stat + structure instead of just the size + +--- + tools/idevicecrashreport.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/idevicecrashreport.c b/tools/idevicecrashreport.c +index 6918d6b..d0b2c7a 100644 +--- a/tools/idevicecrashreport.c ++++ b/tools/idevicecrashreport.c +@@ -135,7 +135,7 @@ static int afc_client_copy_and_remove_crash_reports(afc_client_t afc, const char + + char **fileinfo = NULL; + struct stat stbuf; +- stbuf.st_size = 0; ++ memset(&stbuf, '\0', sizeof(struct stat)); + + /* assemble absolute source filename */ + strcpy(((char*)source_filename) + device_directory_length, list[k]); +-- +2.23.0 + + +From 2332655423c1616d8e37ece7f33e98be0e218504 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Fri, 12 Jul 2019 18:45:46 +0700 +Subject: [PATCH 121/151] Fix service startup in idevicecrashreport for iOS 13 + +--- + tools/idevicecrashreport.c | 34 +++++++++++++++++----------------- + 1 file changed, 17 insertions(+), 17 deletions(-) + +diff --git a/tools/idevicecrashreport.c b/tools/idevicecrashreport.c +index d0b2c7a..533265c 100644 +--- a/tools/idevicecrashreport.c ++++ b/tools/idevicecrashreport.c +@@ -30,9 +30,10 @@ + #include + #include "common/utils.h" + +-#include +-#include + #include ++#include ++#include ++#include + #include + + #ifdef WIN32 +@@ -55,7 +56,8 @@ static int file_exists(const char* path) + #endif + } + +-static int extract_raw_crash_report(const char* filename) { ++static int extract_raw_crash_report(const char* filename) ++{ + int res = 0; + plist_t report = NULL; + char* raw = NULL; +@@ -307,7 +309,8 @@ static void print_usage(int argc, char **argv) + printf("Homepage: <" PACKAGE_URL ">\n"); + } + +-int main(int argc, char* argv[]) { ++int main(int argc, char* argv[]) ++{ + idevice_t device = NULL; + lockdownd_client_t lockdownd = NULL; + afc_client_t afc = NULL; +@@ -396,9 +399,11 @@ int main(int argc, char* argv[]) { + } + + /* trigger move operation on device */ +- idevice_connection_t connection = NULL; +- device_error = idevice_connect(device, service->port, &connection); +- if(device_error != IDEVICE_E_SUCCESS) { ++ service_client_t svcmove = NULL; ++ service_error_t service_error = service_client_new(device, service, &svcmove); ++ lockdownd_service_descriptor_free(service); ++ service = NULL; ++ if (service_error != SERVICE_E_SUCCESS) { + lockdownd_client_free(lockdownd); + idevice_free(device); + return -1; +@@ -410,23 +415,18 @@ int main(int argc, char* argv[]) { + int attempts = 0; + while ((strncmp(ping, "ping", 4) != 0) && (attempts < 10)) { + uint32_t bytes = 0; +- device_error = idevice_connection_receive_timeout(connection, ping, 4, &bytes, 2000); +- if (device_error != IDEVICE_E_SUCCESS) { ++ service_error = service_receive_with_timeout(svcmove, ping, 4, &bytes, 2000); ++ if (service_error == SERVICE_E_SUCCESS || service_error == SERVICE_E_TIMEOUT) { + attempts++; + continue; +- } else if (device_error < 0) { +- fprintf(stderr, "ERROR: Crash logs could not be moved. Connection interrupted.\n"); ++ } else { ++ fprintf(stderr, "ERROR: Crash logs could not be moved. Connection interrupted (%d).\n", service_error); + break; + } + } +- idevice_disconnect(connection); ++ service_client_free(svcmove); + free(ping); + +- if (service) { +- lockdownd_service_descriptor_free(service); +- service = NULL; +- } +- + if (device_error != IDEVICE_E_SUCCESS || attempts > 10) { + fprintf(stderr, "ERROR: Failed to receive ping message from crash report mover.\n"); + lockdownd_client_free(lockdownd); +-- +2.23.0 + + +From f52584e7310ad9af414cdd22cbfad81d53417c22 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Fri, 19 Jul 2019 00:06:38 +0700 +Subject: [PATCH 122/151] OpenSSL: Use SSL_pending() to determine if we want a + select() before SSL_read() + +In order to obey the timeout in idevice_connection_receive_timeout(), we are +using select() via socket_check_fd(). However, the SSL bio might have buffered +more bytes than actually requested upon a call to SSL_read(), so in the next +call to idevice_connection_receive_timeout() a select() would not find the fd +being ready to read, and make it fail with an error, after the specified +timeout is reached. +With the help of SSL_pending() we can now skip calling select() so that +SSL_read() will directly be called again. +--- + src/idevice.c | 27 ++++++++++++++++----------- + 1 file changed, 16 insertions(+), 11 deletions(-) + +diff --git a/src/idevice.c b/src/idevice.c +index 02d34cc..794af8b 100644 +--- a/src/idevice.c ++++ b/src/idevice.c +@@ -453,19 +453,24 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_receive_timeout(idevice_ + + if (connection->ssl_data) { + uint32_t received = 0; ++ int do_select = 1; + + while (received < len) { +- +- int conn_error = socket_check_fd((int)(long)connection->data, FDM_READ, timeout); +- idevice_error_t error = socket_recv_to_idevice_error(conn_error, len, received); +- +- switch (error) { +- case IDEVICE_E_SUCCESS: +- break; +- case IDEVICE_E_UNKNOWN_ERROR: +- debug_info("ERROR: socket_check_fd returned %d (%s)", conn_error, strerror(-conn_error)); +- default: +- return error; ++#ifdef HAVE_OPENSSL ++ do_select = (SSL_pending(connection->ssl_data->session) == 0); ++#endif ++ if (do_select) { ++ int conn_error = socket_check_fd((int)(long)connection->data, FDM_READ, timeout); ++ idevice_error_t error = socket_recv_to_idevice_error(conn_error, len, received); ++ ++ switch (error) { ++ case IDEVICE_E_SUCCESS: ++ break; ++ case IDEVICE_E_UNKNOWN_ERROR: ++ debug_info("ERROR: socket_check_fd returned %d (%s)", conn_error, strerror(-conn_error)); ++ default: ++ return error; ++ } + } + + #ifdef HAVE_OPENSSL +-- +2.23.0 + + +From e87c26ebe58aa9b778a06ebbb94659a1ef304e38 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Fri, 19 Jul 2019 02:15:40 +0700 +Subject: [PATCH 123/151] syslog_relay: Terminate worker thread before freeing + service client to prevent segfault + +--- + src/syslog_relay.c | 9 +-------- + 1 file changed, 1 insertion(+), 8 deletions(-) + +diff --git a/src/syslog_relay.c b/src/syslog_relay.c +index 0d71392..579908c 100644 +--- a/src/syslog_relay.c ++++ b/src/syslog_relay.c +@@ -104,15 +104,8 @@ LIBIMOBILEDEVICE_API syslog_relay_error_t syslog_relay_client_free(syslog_relay_ + { + if (!client) + return SYSLOG_RELAY_E_INVALID_ARG; +- ++ syslog_relay_stop_capture(client); + syslog_relay_error_t err = syslog_relay_error(service_client_free(client->parent)); +- client->parent = NULL; +- if (client->worker) { +- debug_info("Joining syslog capture callback worker thread"); +- thread_join(client->worker); +- thread_free(client->worker); +- client->worker = THREAD_T_NULL; +- } + free(client); + + return err; +-- +2.23.0 + + +From 98ac7da5255a69fa4620e325228a1c7d79ba42d7 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Fri, 19 Jul 2019 02:21:51 +0700 +Subject: [PATCH 124/151] installation_proxy: Terminate worker thread before + freeing property list service client to prevent segfault + +--- + src/installation_proxy.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/installation_proxy.c b/src/installation_proxy.c +index 7c2d336..9a6f1ab 100644 +--- a/src/installation_proxy.c ++++ b/src/installation_proxy.c +@@ -261,7 +261,7 @@ LIBIMOBILEDEVICE_API instproxy_error_t instproxy_client_free(instproxy_client_t + if (!client) + return INSTPROXY_E_INVALID_ARG; + +- property_list_service_client_free(client->parent); ++ property_list_service_client_t parent = client->parent; + client->parent = NULL; + if (client->receive_status_thread) { + debug_info("joining receive_status_thread"); +@@ -269,6 +269,7 @@ LIBIMOBILEDEVICE_API instproxy_error_t instproxy_client_free(instproxy_client_t + thread_free(client->receive_status_thread); + client->receive_status_thread = THREAD_T_NULL; + } ++ property_list_service_client_free(parent); + mutex_destroy(&client->mutex); + free(client); + +-- +2.23.0 + + +From a9ccd31ddd5d59db8dc5114c7c85e3eac8743578 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Sun, 18 Aug 2019 01:57:44 +0200 +Subject: [PATCH 125/151] Force use of TLSv1 for backwards compatibility with + older iOS versions + +--- + src/idevice.c | 14 +++++++++++++- + 1 file changed, 13 insertions(+), 1 deletion(-) + +diff --git a/src/idevice.c b/src/idevice.c +index 794af8b..38fc015 100644 +--- a/src/idevice.c ++++ b/src/idevice.c +@@ -789,6 +789,18 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_enable_ssl(idevice_conne + return ret; + } + ++ /* force use of TLSv1 */ ++#ifdef SSL_OP_NO_TLSv1_1 ++ int opts = SSL_OP_NO_TLSv1_1; ++#ifdef SSL_OP_NO_TLSv1_2 ++ opts |= SSL_OP_NO_TLSv1_2; ++#endif ++#ifdef SSL_OP_NO_TLSv1_3 ++ opts |= SSL_OP_NO_TLSv1_3; ++#endif ++ SSL_CTX_set_options(ssl_ctx, SSL_OP_ALL | opts); ++#endif ++ + BIO* membp; + X509* rootCert = NULL; + membp = BIO_new_mem_buf(root_cert.data, root_cert.size); +@@ -832,7 +844,7 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_enable_ssl(idevice_conne + ssl_data_loc->ctx = ssl_ctx; + connection->ssl_data = ssl_data_loc; + ret = IDEVICE_E_SUCCESS; +- debug_info("SSL mode enabled, cipher: %s", SSL_get_cipher(ssl)); ++ debug_info("SSL mode enabled, %s, cipher: %s", SSL_get_version(ssl), SSL_get_cipher(ssl)); + } + /* required for proper multi-thread clean up to prevent leaks */ + openssl_remove_thread_state(); +-- +2.23.0 + + +From 9e33a26264ab6abe9eea10b7aa11f948b4bde87e Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Sun, 18 Aug 2019 16:11:38 +0200 +Subject: [PATCH 126/151] idevice: [win32] Move windows.h include after + socket.h to prevent 'must include winsock.h before windows.h' + +--- + src/idevice.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/src/idevice.c b/src/idevice.c +index 38fc015..382e9d2 100644 +--- a/src/idevice.c ++++ b/src/idevice.c +@@ -29,10 +29,6 @@ + #include + #include + +-#ifdef WIN32 +-#include +-#endif +- + #include + #ifdef HAVE_OPENSSL + #include +@@ -48,6 +44,10 @@ + #include "common/thread.h" + #include "common/debug.h" + ++#ifdef WIN32 ++#include ++#endif ++ + #ifdef HAVE_OPENSSL + + #if OPENSSL_VERSION_NUMBER < 0x10100000L || \ +-- +2.23.0 + + +From 5086a9751f5c1298ac423a52b63ca299130aa1c2 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Wed, 28 Aug 2019 03:06:18 +0200 +Subject: [PATCH 127/151] Add preboardservice_v2 implementation + +--- + include/Makefile.am | 1 + + include/libimobiledevice/preboard.h | 168 +++++++++++++++ + src/Makefile.am | 1 + + src/preboard.c | 318 ++++++++++++++++++++++++++++ + src/preboard.h | 34 +++ + 5 files changed, 522 insertions(+) + create mode 100644 include/libimobiledevice/preboard.h + create mode 100644 src/preboard.c + create mode 100644 src/preboard.h + +diff --git a/include/Makefile.am b/include/Makefile.am +index f2b93ed..eaf052a 100644 +--- a/include/Makefile.am ++++ b/include/Makefile.am +@@ -21,5 +21,6 @@ nobase_include_HEADERS = libimobiledevice/libimobiledevice.h \ + libimobiledevice/debugserver.h\ + libimobiledevice/syslog_relay.h\ + libimobiledevice/mobileactivation.h\ ++ libimobiledevice/preboard.h\ + libimobiledevice/property_list_service.h\ + libimobiledevice/service.h +diff --git a/include/libimobiledevice/preboard.h b/include/libimobiledevice/preboard.h +new file mode 100644 +index 0000000..dc4e5f3 +--- /dev/null ++++ b/include/libimobiledevice/preboard.h +@@ -0,0 +1,168 @@ ++/** ++ * @file libimobiledevice/preboard.h ++ * @brief Service to 'preboard' a device, which allows to ask for passcode during firmware updates. ++ * \internal ++ * ++ * Copyright (c) 2019 Nikias Bassen, All Rights Reserved. ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#ifndef IPREBOARD_H ++#define IPREBOARD_H ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#include ++#include ++ ++#define PREBOARD_SERVICE_NAME "com.apple.preboardservice_v2" ++ ++/** Error Codes */ ++typedef enum { ++ PREBOARD_E_SUCCESS = 0, ++ PREBOARD_E_INVALID_ARG = -1, ++ PREBOARD_E_PLIST_ERROR = -2, ++ PREBOARD_E_MUX_ERROR = -3, ++ PREBOARD_E_SSL_ERROR = -4, ++ PREBOARD_E_NOT_ENOUGH_DATA = -5, ++ PREBOARD_E_TIMEOUT = -6, ++ PREBOARD_E_OP_IN_PROGRESS = -10, ++ PREBOARD_E_UNKNOWN_ERROR = -256 ++} preboard_error_t; ++ ++typedef struct preboard_client_private preboard_client_private; ++typedef preboard_client_private *preboard_client_t; /**< The client handle. */ ++ ++/** Reports the status response of the given command */ ++typedef void (*preboard_status_cb_t) (plist_t message, void *user_data); ++ ++/** ++ * Connects to the preboard service on the specified device. ++ * ++ * @param device The device to connect to. ++ * @param service The service descriptor returned by lockdownd_start_service. ++ * @param client Pointer that will point to a newly allocated ++ * preboard_client_t upon successful return. Must be freed using ++ * preboard_client_free() after use. ++ * ++ * @return PREBOARD_E_SUCCESS on success, PREBOARD_E_INVALID_ARG when ++ * client is NULL, or an PREBOARD_E_* error code otherwise. ++ */ ++preboard_error_t preboard_client_new(idevice_t device, lockdownd_service_descriptor_t service, preboard_client_t * client); ++ ++/** ++ * Starts a new preboard service on the specified device and connects to it. ++ * ++ * @param device The device to connect to. ++ * @param client Pointer that will point to a newly allocated ++ * preboard_client_t upon successful return. Must be freed using ++ * preboard_client_free() after use. ++ * @param label The label to use for communication. Usually the program name. ++ * Pass NULL to disable sending the label in requests to lockdownd. ++ * ++ * @return PREBOARD_E_SUCCESS on success, or a PREBOARD_E_* error ++ * code otherwise. ++ */ ++preboard_error_t preboard_client_start_service(idevice_t device, preboard_client_t * client, const char* label); ++ ++/** ++ * Disconnects a preboard client from the device and frees up the ++ * preboard client data. ++ * ++ * @param client The preboard client to disconnect and free. ++ * ++ * @return PREBOARD_E_SUCCESS on success, PREBOARD_E_INVALID_ARG when ++ * client is NULL, or a PREBOARD_E_* error code otherwise. ++ */ ++preboard_error_t preboard_client_free(preboard_client_t client); ++ ++/** ++ * Sends a plist to the service. ++ * ++ * @param client The preboard client ++ * @param plist The plist to send ++ * ++ * @return PREBOARD_E_SUCCESS on success, ++ * PREBOARD_E_INVALID_ARG when client or plist is NULL, ++ * or a PREBOARD_E_* error code on error ++ */ ++preboard_error_t preboard_send(preboard_client_t client, plist_t plist); ++ ++/** ++ * Receives a plist from the service. ++ * ++ * @param client The preboard client ++ * @param plist Pointer to a plist_t what will be set to the received plist ++ * ++ * @return PREBOARD_E_SUCCESS on success, ++ * PREBOARD_E_INVALID_ARG when client or plist is NULL, ++ * PREBOARD_E_TIMEOUT when no data was received after 5 seconds, ++ * or a PREBOARD_E_* error code on error ++ */ ++preboard_error_t preboard_receive(preboard_client_t client, plist_t * plist); ++ ++/** ++ * Receives a plist from the service with the specified timeout. ++ * ++ * @param client The preboard client ++ * @param plist Pointer to a plist_t what will be set to the received plist ++ * ++ * @return PREBOARD_E_SUCCESS on success, ++ * PREBOARD_E_INVALID_ARG when client or plist is NULL, ++ * PREBOARD_E_TIMEOUT when no data was received after the given timeout, ++ * or a PREBOARD_E_* error code on error. ++ */ ++preboard_error_t preboard_receive_with_timeout(preboard_client_t client, plist_t * plist, uint32_t timeout_ms); ++ ++/** ++ * Tells the preboard service to create a stashbag. This will make the device ++ * show a passcode entry so it can generate and store a token that is later ++ * used during restore. ++ * ++ * @param client The preboard client ++ * @param manifest An optional manifest ++ * @param status_cb Callback function that will receive status and error messages. ++ * Can be NULL if you want to handle receiving messages in your own code. ++ * @param user_data User data for callback function or NULL. ++ * ++ * @return PREBOARD_E_SUCCESS if the command was successfully submitted, ++ * PREBOARD_E_INVALID_ARG when client is invalid, ++ * or a PREBOARD_E_* error code on error. ++ */ ++preboard_error_t preboard_create_stashbag(preboard_client_t client, plist_t manifest, preboard_status_cb_t status_cb, void *user_data); ++ ++/** ++ * Instructs the preboard service to commit a previously created stashbag. ++ * ++ * @param client The preboard client to use for receiving ++ * @param manifest An optional manifest ++ * @param status_cb Callback function that will receive status and error messages ++ * Can be NULL if you want to handle receiving messages in your own code. ++ * @param user_data User data for callback function or NULL. ++ * ++ * @return PREBOARD_E_SUCCESS if the command was successfully submitted, ++ * PREBOARD_E_INVALID_ARG when client is invalid, ++ * or a PREBOARD_E_* error code on error. ++ */ ++preboard_error_t preboard_commit_stashbag(preboard_client_t client, plist_t manifest, preboard_status_cb_t status_cb, void *user_data); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +diff --git a/src/Makefile.am b/src/Makefile.am +index fcde8ae..5fcf097 100644 +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -29,6 +29,7 @@ libimobiledevice_la_SOURCES = idevice.c idevice.h \ + debugserver.c debugserver.h\ + webinspector.c webinspector.h\ + mobileactivation.c mobileactivation.h\ ++ preboard.c preboard.h \ + syslog_relay.c syslog_relay.h + + if WIN32 +diff --git a/src/preboard.c b/src/preboard.c +new file mode 100644 +index 0000000..7b27a34 +--- /dev/null ++++ b/src/preboard.c +@@ -0,0 +1,318 @@ ++/* ++ * preboard.c ++ * com.apple.preboardservice_v2 service implementation. ++ * ++ * Copyright (c) 2019 Nikias Bassen, All Rights Reserved. ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#ifdef HAVE_CONFIG_H ++#include ++#endif ++#include ++#include ++#include ++ ++#include "preboard.h" ++#include "lockdown.h" ++#include "common/debug.h" ++ ++/** ++ * Convert a property_list_service_error_t value to a preboard_error_t value. ++ * Used internally to get correct error codes. ++ * ++ * @param err An property_list_service_error_t error code ++ * ++ * @return A matching preboard_error_t error code, ++ * PREBOARD_E_UNKNOWN_ERROR otherwise. ++ */ ++static preboard_error_t preboard_error(property_list_service_error_t err) ++{ ++ switch (err) { ++ case PROPERTY_LIST_SERVICE_E_SUCCESS: ++ return PREBOARD_E_SUCCESS; ++ case PROPERTY_LIST_SERVICE_E_INVALID_ARG: ++ return PREBOARD_E_INVALID_ARG; ++ case PROPERTY_LIST_SERVICE_E_PLIST_ERROR: ++ return PREBOARD_E_PLIST_ERROR; ++ case PROPERTY_LIST_SERVICE_E_MUX_ERROR: ++ return PREBOARD_E_MUX_ERROR; ++ case PROPERTY_LIST_SERVICE_E_SSL_ERROR: ++ return PREBOARD_E_SSL_ERROR; ++ case PROPERTY_LIST_SERVICE_E_NOT_ENOUGH_DATA: ++ return PREBOARD_E_NOT_ENOUGH_DATA; ++ case PROPERTY_LIST_SERVICE_E_RECEIVE_TIMEOUT: ++ return PREBOARD_E_TIMEOUT; ++ default: ++ break; ++ } ++ return PREBOARD_E_UNKNOWN_ERROR; ++} ++ ++LIBIMOBILEDEVICE_API preboard_error_t preboard_client_new(idevice_t device, lockdownd_service_descriptor_t service, preboard_client_t * client) ++{ ++ *client = NULL; ++ ++ if (!device || !service || service->port == 0 || !client || *client) { ++ debug_info("Incorrect parameter passed to preboard_client_new."); ++ return PREBOARD_E_INVALID_ARG; ++ } ++ ++ debug_info("Creating preboard_client, port = %d.", service->port); ++ ++ property_list_service_client_t plclient = NULL; ++ preboard_error_t ret = preboard_error(property_list_service_client_new(device, service, &plclient)); ++ if (ret != PREBOARD_E_SUCCESS) { ++ debug_info("Creating a property list client failed. Error: %i", ret); ++ return ret; ++ } ++ ++ preboard_client_t client_loc = (preboard_client_t) malloc(sizeof(struct preboard_client_private)); ++ client_loc->parent = plclient; ++ client_loc->receive_status_thread = THREAD_T_NULL; ++ ++ *client = client_loc; ++ ++ debug_info("preboard_client successfully created."); ++ return 0; ++} ++ ++LIBIMOBILEDEVICE_API preboard_error_t preboard_client_start_service(idevice_t device, preboard_client_t * client, const char* label) ++{ ++ preboard_error_t err = PREBOARD_E_UNKNOWN_ERROR; ++ service_client_factory_start_service(device, PREBOARD_SERVICE_NAME, (void**)client, label, SERVICE_CONSTRUCTOR(preboard_client_new), &err); ++ return err; ++} ++ ++LIBIMOBILEDEVICE_API preboard_error_t preboard_client_free(preboard_client_t client) ++{ ++ if (!client) ++ return PREBOARD_E_INVALID_ARG; ++ ++ property_list_service_client_t parent = client->parent; ++ client->parent = NULL; ++ if (client->receive_status_thread) { ++ debug_info("joining receive_status_thread"); ++ thread_join(client->receive_status_thread); ++ thread_free(client->receive_status_thread); ++ client->receive_status_thread = THREAD_T_NULL; ++ } ++ preboard_error_t err = preboard_error(property_list_service_client_free(parent)); ++ free(client); ++ ++ return err; ++} ++ ++LIBIMOBILEDEVICE_API preboard_error_t preboard_send(preboard_client_t client, plist_t plist) ++{ ++ preboard_error_t res = PREBOARD_E_UNKNOWN_ERROR; ++ res = preboard_error(property_list_service_send_binary_plist(client->parent, plist)); ++ if (res != PREBOARD_E_SUCCESS) { ++ debug_info("Sending plist failed with error %d", res); ++ return res; ++ } ++ return res; ++} ++ ++LIBIMOBILEDEVICE_API preboard_error_t preboard_receive_with_timeout(preboard_client_t client, plist_t * plist, uint32_t timeout_ms) ++{ ++ preboard_error_t res = PREBOARD_E_UNKNOWN_ERROR; ++ plist_t outplist = NULL; ++ res = preboard_error(property_list_service_receive_plist_with_timeout(client->parent, &outplist, timeout_ms)); ++ if (res != PREBOARD_E_SUCCESS && res != PREBOARD_E_TIMEOUT) { ++ debug_info("Could not receive plist, error %d", res); ++ plist_free(outplist); ++ } else if (res == PREBOARD_E_SUCCESS) { ++ *plist = outplist; ++ } ++ return res; ++} ++ ++LIBIMOBILEDEVICE_API preboard_error_t preboard_receive(preboard_client_t client, plist_t * plist) ++{ ++ return preboard_receive_with_timeout(client, plist, 5000); ++} ++ ++struct preboard_status_data { ++ preboard_client_t client; ++ preboard_status_cb_t cbfunc; ++ void *user_data; ++}; ++ ++static void* preboard_receive_status_loop_thread(void* arg) ++{ ++ struct preboard_status_data *data = (struct preboard_status_data*)arg; ++ ++ /* run until the service disconnects or an error occurs */ ++ while (data->client && data->client->parent) { ++ plist_t pl = NULL; ++ preboard_error_t perr = preboard_receive_with_timeout(data->client, &pl, 1000); ++ if (perr == PREBOARD_E_TIMEOUT) { ++ continue; ++ } else if (perr == PREBOARD_E_SUCCESS) { ++ data->cbfunc(pl, data->user_data); ++ } ++ plist_free(pl); ++ if (perr != PREBOARD_E_SUCCESS) { ++ data->cbfunc(NULL, data->user_data); ++ break; ++ } ++ } ++ ++ /* cleanup */ ++ debug_info("done, cleaning up."); ++ ++ if (data->client->receive_status_thread) { ++ thread_free(data->client->receive_status_thread); ++ data->client->receive_status_thread = THREAD_T_NULL; ++ } ++ free(data); ++ ++ return NULL; ++} ++ ++static preboard_error_t preboard_receive_status_loop_with_callback(preboard_client_t client, preboard_status_cb_t status_cb, void *user_data) ++{ ++ if (!client || !client->parent) { ++ return PREBOARD_E_INVALID_ARG; ++ } ++ ++ if (client->receive_status_thread) { ++ return PREBOARD_E_OP_IN_PROGRESS; ++ } ++ ++ preboard_error_t res = PREBOARD_E_UNKNOWN_ERROR; ++ struct preboard_status_data *data = (struct preboard_status_data*)malloc(sizeof(struct preboard_status_data)); ++ if (data) { ++ data->client = client; ++ data->cbfunc = status_cb; ++ data->user_data = user_data; ++ if (thread_new(&client->receive_status_thread, preboard_receive_status_loop_thread, data) == 0) { ++ res = PREBOARD_E_SUCCESS; ++ } ++ } ++ ++ return res; ++} ++ ++LIBIMOBILEDEVICE_API preboard_error_t preboard_create_stashbag(preboard_client_t client, plist_t manifest, preboard_status_cb_t status_cb, void *user_data) ++{ ++ if (!client) { ++ return PREBOARD_E_INVALID_ARG; ++ } ++ ++ plist_t dict = plist_new_dict(); ++ plist_dict_set_item(dict, "Command", plist_new_string("CreateStashbag")); ++ if (manifest) { ++ plist_dict_set_item(dict, "Manifest", plist_copy(manifest)); ++ } ++ preboard_error_t perr = preboard_send(client, dict); ++ plist_free(dict); ++ if (perr != PREBOARD_E_SUCCESS) { ++ return perr; ++ } ++ if (!status_cb) { ++ return PREBOARD_E_SUCCESS; ++ } ++ ++ return preboard_receive_status_loop_with_callback(client, status_cb, user_data); ++ ++ // return { ShowDialog: true} or {Timeout: true} followed by {HideDialog: true} ++ // or { Error: 1, ErrorString: } ++ ++ ++/* ++ ++ ++ ++ ++ ShowDialog ++ ++ Version ++ 2 ++ ++ ++ ++for success, it will send the HideDialog message, then wait up to 14400 seconds (4h) for the device to reboot? ++ ++ ++ ++ ++ ++ ++ ++ ++ Error ++ 1 ++ ErrorString ++ user authentication failed: Error Domain=com.apple.LocalAuthentication Code=-2 "Canceled by user." UserInfo={BiometryType=1, NSLocalizedDescription=Canceled by user.} ++ Version ++ 2 ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ Timeout ++ ++ Version ++ 2 ++ ++ ++ ++ ++ ++ ++ ++ HideDialog ++ ++ Version ++ 2 ++ ++ ++ ++*/ ++} ++ ++LIBIMOBILEDEVICE_API preboard_error_t preboard_commit_stashbag(preboard_client_t client, plist_t manifest, preboard_status_cb_t status_cb, void *user_data) ++{ ++ // returns { StashbagCommitComplete: true } ++ // or { StashbagCommitComplete: 0, Error: 1, ErrorString: } ++ ++ if (!client) { ++ return PREBOARD_E_INVALID_ARG; ++ } ++ ++ plist_t dict = plist_new_dict(); ++ plist_dict_set_item(dict, "Command", plist_new_string("CommitStashbag")); ++ if (manifest) { ++ plist_dict_set_item(dict, "Manifest", plist_copy(manifest)); ++ } ++ preboard_error_t perr = preboard_send(client, dict); ++ plist_free(dict); ++ if (perr != PREBOARD_E_SUCCESS) { ++ return perr; ++ } ++ if (!status_cb) { ++ return PREBOARD_E_SUCCESS; ++ } ++ ++ return preboard_receive_status_loop_with_callback(client, status_cb, user_data); ++} +diff --git a/src/preboard.h b/src/preboard.h +new file mode 100644 +index 0000000..c5143a9 +--- /dev/null ++++ b/src/preboard.h +@@ -0,0 +1,34 @@ ++/* ++ * preboard.h ++ * com.apple.preboard_v2 service header file. ++ * ++ * Copyright (c) 2019 Nikias Bassen, All Rights Reserved. ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#ifndef __PREBOARD_H ++#define __PREBOARD_H ++ ++#include "libimobiledevice/preboard.h" ++#include "property_list_service.h" ++#include "common/thread.h" ++ ++struct preboard_client_private { ++ property_list_service_client_t parent; ++ THREAD_T receive_status_thread; ++}; ++ ++#endif +-- +2.23.0 + + +From 6d5a3d6a35a8610f83d6a69156cfe1b64da4f2bd Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Thu, 29 Aug 2019 08:29:14 +0200 +Subject: [PATCH 128/151] preboard: Remove development notes from preboard.c + and add info to public header + +--- + include/libimobiledevice/preboard.h | 17 ++++++++ + src/preboard.c | 63 ----------------------------- + 2 files changed, 17 insertions(+), 63 deletions(-) + +diff --git a/include/libimobiledevice/preboard.h b/include/libimobiledevice/preboard.h +index dc4e5f3..60b8e26 100644 +--- a/include/libimobiledevice/preboard.h ++++ b/include/libimobiledevice/preboard.h +@@ -140,6 +140,17 @@ preboard_error_t preboard_receive_with_timeout(preboard_client_t client, plist_t + * Can be NULL if you want to handle receiving messages in your own code. + * @param user_data User data for callback function or NULL. + * ++ * The callback or following preboard_receive* invocations will usually ++ * receive a dictionary with: ++ * { ShowDialog: true } ++ * If the user does not enter a passcode, after 2 minutes a timeout is reached ++ * and the device sends a dictionary with: ++ * { Timeout: true } ++ * followed by { HideDialog: true } ++ * If the user aborts the passcode entry, the device sends a dictionary: ++ * { Error: 1, ErrorString: } ++ * followed by { HideDialog: true } ++ * + * @return PREBOARD_E_SUCCESS if the command was successfully submitted, + * PREBOARD_E_INVALID_ARG when client is invalid, + * or a PREBOARD_E_* error code on error. +@@ -155,6 +166,12 @@ preboard_error_t preboard_create_stashbag(preboard_client_t client, plist_t mani + * Can be NULL if you want to handle receiving messages in your own code. + * @param user_data User data for callback function or NULL. + * ++ * The callback or following preboard_receive* invocations will usually ++ * receive a dictionary with: ++ * { StashbagCommitComplete: true } ++ * or in case of an error: ++ * { StashbagCommitComplete: 0, Error: 1, ErrorString: } ++ * + * @return PREBOARD_E_SUCCESS if the command was successfully submitted, + * PREBOARD_E_INVALID_ARG when client is invalid, + * or a PREBOARD_E_* error code on error. +diff --git a/src/preboard.c b/src/preboard.c +index 7b27a34..b975f0e 100644 +--- a/src/preboard.c ++++ b/src/preboard.c +@@ -229,73 +229,10 @@ LIBIMOBILEDEVICE_API preboard_error_t preboard_create_stashbag(preboard_client_t + } + + return preboard_receive_status_loop_with_callback(client, status_cb, user_data); +- +- // return { ShowDialog: true} or {Timeout: true} followed by {HideDialog: true} +- // or { Error: 1, ErrorString: } +- +- +-/* +- +- +- +- +- ShowDialog +- +- Version +- 2 +- +- +- +-for success, it will send the HideDialog message, then wait up to 14400 seconds (4h) for the device to reboot? +- +- +- +- +- +- +- +- +- Error +- 1 +- ErrorString +- user authentication failed: Error Domain=com.apple.LocalAuthentication Code=-2 "Canceled by user." UserInfo={BiometryType=1, NSLocalizedDescription=Canceled by user.} +- Version +- 2 +- +- +- +- +- +- +- +- +- +- Timeout +- +- Version +- 2 +- +- +- +- +- +- +- +- HideDialog +- +- Version +- 2 +- +- +- +-*/ + } + + LIBIMOBILEDEVICE_API preboard_error_t preboard_commit_stashbag(preboard_client_t client, plist_t manifest, preboard_status_cb_t status_cb, void *user_data) + { +- // returns { StashbagCommitComplete: true } +- // or { StashbagCommitComplete: 0, Error: 1, ErrorString: } +- + if (!client) { + return PREBOARD_E_INVALID_ARG; + } +-- +2.23.0 + + +From a9e69b1252e5918b6d8ada1209ccefde301cfa26 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Thu, 5 Sep 2019 19:50:24 +0200 +Subject: [PATCH 129/151] idevice: Fix handling SSL/TLS version selection for + OpenSSL 1.1.0+ and for older devices + +--- + src/idevice.c | 30 +++++++++++++++++++----------- + src/idevice.h | 4 +++- + src/lockdown.c | 4 ++-- + 3 files changed, 24 insertions(+), 14 deletions(-) + +diff --git a/src/idevice.c b/src/idevice.c +index 382e9d2..fd1f4b5 100644 +--- a/src/idevice.c ++++ b/src/idevice.c +@@ -320,7 +320,7 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connect(idevice_t device, uint16_t + new_connection->type = CONNECTION_USBMUXD; + new_connection->data = (void*)(long)sfd; + new_connection->ssl_data = NULL; +- idevice_get_udid(device, &new_connection->udid); ++ new_connection->device = device; + *connection = new_connection; + return IDEVICE_E_SUCCESS; + } else { +@@ -348,9 +348,6 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_disconnect(idevice_connection_t con + debug_info("Unknown connection type %d", connection->type); + } + +- if (connection->udid) +- free(connection->udid); +- + free(connection); + connection = NULL; + +@@ -759,9 +756,9 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_enable_ssl(idevice_conne + #endif + plist_t pair_record = NULL; + +- userpref_read_pair_record(connection->udid, &pair_record); ++ userpref_read_pair_record(connection->device->udid, &pair_record); + if (!pair_record) { +- debug_info("ERROR: Failed enabling SSL. Unable to read pair record for udid %s.", connection->udid); ++ debug_info("ERROR: Failed enabling SSL. Unable to read pair record for udid %s.", connection->device->udid); + return ret; + } + +@@ -789,16 +786,27 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_enable_ssl(idevice_conne + return ret; + } + +- /* force use of TLSv1 */ ++#if OPENSSL_VERSION_NUMBER < 0x10100002L || \ ++ (defined(LIBRESSL_VERSION_NUMBER) && (LIBRESSL_VERSION_NUMBER < 0x2060000fL)) ++ /* force use of TLSv1 for older devices */ ++ if (connection->device->version < DEVICE_VERSION(10,0,0)) { + #ifdef SSL_OP_NO_TLSv1_1 +- int opts = SSL_OP_NO_TLSv1_1; ++ long opts = SSL_CTX_get_options(ssl_ctx); ++ opts |= SSL_OP_NO_TLSv1_1; + #ifdef SSL_OP_NO_TLSv1_2 +- opts |= SSL_OP_NO_TLSv1_2; ++ opts |= SSL_OP_NO_TLSv1_2; + #endif + #ifdef SSL_OP_NO_TLSv1_3 +- opts |= SSL_OP_NO_TLSv1_3; ++ opts |= SSL_OP_NO_TLSv1_3; ++#endif ++ SSL_CTX_set_options(ssl_ctx, opts); + #endif +- SSL_CTX_set_options(ssl_ctx, SSL_OP_ALL | opts); ++ } ++#else ++ SSL_CTX_set_min_proto_version(ssl_ctx, TLS1_VERSION); ++ if (connection->device->version < DEVICE_VERSION(10,0,0)) { ++ SSL_CTX_set_max_proto_version(ssl_ctx, TLS1_VERSION); ++ } + #endif + + BIO* membp; +diff --git a/src/idevice.h b/src/idevice.h +index 94e828b..f403c55 100644 +--- a/src/idevice.h ++++ b/src/idevice.h +@@ -46,6 +46,8 @@ + #include "common/userpref.h" + #include "libimobiledevice/libimobiledevice.h" + ++#define DEVICE_VERSION(maj, min, patch) (((maj & 0xFF) << 16) | ((min & 0xFF) << 8) | (patch & 0xFF)) ++ + enum connection_type { + CONNECTION_USBMUXD = 1 + }; +@@ -66,7 +68,7 @@ struct ssl_data_private { + typedef struct ssl_data_private *ssl_data_t; + + struct idevice_connection_private { +- char *udid; ++ idevice_t device; + enum connection_type type; + void *data; + ssl_data_t ssl_data; +diff --git a/src/lockdown.c b/src/lockdown.c +index 23f2782..694fb47 100644 +--- a/src/lockdown.c ++++ b/src/lockdown.c +@@ -715,7 +715,7 @@ LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_client_new_with_handshake(idevi + char *s_version = NULL; + plist_get_string_val(p_version, &s_version); + if (s_version && sscanf(s_version, "%d.%d.%d", &vers[0], &vers[1], &vers[2]) >= 2) { +- device->version = ((vers[0] & 0xFF) << 16) | ((vers[1] & 0xFF) << 8) | (vers[2] & 0xFF); ++ device->version = DEVICE_VERSION(vers[0], vers[1], vers[2]); + } + free(s_version); + } +@@ -738,7 +738,7 @@ LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_client_new_with_handshake(idevi + plist_free(pair_record); + pair_record = NULL; + +- if (device->version < 0x070000) { ++ if (device->version < DEVICE_VERSION(7,0,0)) { + /* for older devices, we need to validate pairing to receive trusted host status */ + ret = lockdownd_validate_pair(client_loc, NULL); + +-- +2.23.0 + + +From acf0a76be3c81a8ce69817af2b16a546a08f7ecb Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Wed, 25 Sep 2019 19:29:28 +0200 +Subject: [PATCH 130/151] restore: Update error codes and properly convert + underlying property_list_service errors + +--- + include/libimobiledevice/restore.h | 11 +++---- + src/restore.c | 52 +++++++++++++++--------------- + 2 files changed, 30 insertions(+), 33 deletions(-) + +diff --git a/include/libimobiledevice/restore.h b/include/libimobiledevice/restore.h +index 897c07c..950f8fd 100644 +--- a/include/libimobiledevice/restore.h ++++ b/include/libimobiledevice/restore.h +@@ -35,13 +35,10 @@ extern "C" { + typedef enum { + RESTORE_E_SUCCESS = 0, + RESTORE_E_INVALID_ARG = -1, +- RESTORE_E_INVALID_CONF = -2, +- RESTORE_E_PLIST_ERROR = -3, +- RESTORE_E_DICT_ERROR = -4, +- RESTORE_E_NOT_ENOUGH_DATA = -5, +- RESTORE_E_MUX_ERROR = -6, +- RESTORE_E_START_RESTORE_FAILED = -7, +- RESTORE_E_DEVICE_ERROR = -8, ++ RESTORE_E_PLIST_ERROR = -2, ++ RESTORE_E_MUX_ERROR = -3, ++ RESTORE_E_NOT_ENOUGH_DATA = -4, ++ RESTORE_E_RECEIVE_TIMEOUT = -5, + RESTORE_E_UNKNOWN_ERROR = -256 + } restored_error_t; + +diff --git a/src/restore.c b/src/restore.c +index 6571a2f..0a13698 100644 +--- a/src/restore.c ++++ b/src/restore.c +@@ -89,6 +89,25 @@ static void plist_dict_add_label(plist_t plist, const char *label) + } + } + ++static restored_error_t restored_error(property_list_service_error_t err) ++{ ++ switch (err) { ++ case PROPERTY_LIST_SERVICE_E_SUCCESS: ++ return RESTORE_E_SUCCESS; ++ case PROPERTY_LIST_SERVICE_E_INVALID_ARG: ++ return RESTORE_E_INVALID_ARG; ++ case PROPERTY_LIST_SERVICE_E_PLIST_ERROR: ++ return RESTORE_E_PLIST_ERROR; ++ case PROPERTY_LIST_SERVICE_E_MUX_ERROR: ++ return RESTORE_E_MUX_ERROR; ++ case PROPERTY_LIST_SERVICE_E_RECEIVE_TIMEOUT: ++ return RESTORE_E_RECEIVE_TIMEOUT; ++ default: ++ break; ++ } ++ return RESTORE_E_UNKNOWN_ERROR; ++} ++ + LIBIMOBILEDEVICE_API restored_error_t restored_client_free(restored_client_t client) + { + if (!client) +@@ -99,9 +118,7 @@ LIBIMOBILEDEVICE_API restored_error_t restored_client_free(restored_client_t cli + if (client->parent) { + restored_goodbye(client); + +- if (property_list_service_client_free(client->parent) == PROPERTY_LIST_SERVICE_E_SUCCESS) { +- ret = RESTORE_E_SUCCESS; +- } ++ ret = restored_error(property_list_service_client_free(client->parent)); + } + + if (client->udid) { +@@ -134,18 +151,7 @@ LIBIMOBILEDEVICE_API restored_error_t restored_receive(restored_client_t client, + if (!client || !plist || (plist && *plist)) + return RESTORE_E_INVALID_ARG; + +- restored_error_t ret = RESTORE_E_SUCCESS; +- property_list_service_error_t err; +- +- err = property_list_service_receive_plist(client->parent, plist); +- if (err != PROPERTY_LIST_SERVICE_E_SUCCESS) { +- ret = RESTORE_E_UNKNOWN_ERROR; +- } +- +- if (!*plist) +- ret = RESTORE_E_PLIST_ERROR; +- +- return ret; ++ return restored_error(property_list_service_receive_plist(client->parent, plist)); + } + + LIBIMOBILEDEVICE_API restored_error_t restored_send(restored_client_t client, plist_t plist) +@@ -153,14 +159,7 @@ LIBIMOBILEDEVICE_API restored_error_t restored_send(restored_client_t client, pl + if (!client || !plist) + return RESTORE_E_INVALID_ARG; + +- restored_error_t ret = RESTORE_E_SUCCESS; +- property_list_service_error_t err; +- +- err = property_list_service_send_xml_plist(client->parent, plist); +- if (err != PROPERTY_LIST_SERVICE_E_SUCCESS) { +- ret = RESTORE_E_UNKNOWN_ERROR; +- } +- return ret; ++ return restored_error(property_list_service_send_xml_plist(client->parent, plist)); + } + + LIBIMOBILEDEVICE_API restored_error_t restored_query_type(restored_client_t client, char **type, uint64_t *version) +@@ -305,9 +304,10 @@ LIBIMOBILEDEVICE_API restored_error_t restored_client_new(idevice_t device, rest + }; + + property_list_service_client_t plistclient = NULL; +- if (property_list_service_client_new(device, (lockdownd_service_descriptor_t)&service, &plistclient) != PROPERTY_LIST_SERVICE_E_SUCCESS) { ++ ret = restored_error(property_list_service_client_new(device, (lockdownd_service_descriptor_t)&service, &plistclient)); ++ if (ret != RESTORE_E_SUCCESS) { + debug_info("could not connect to restored (device %s)", device->udid); +- return RESTORE_E_MUX_ERROR; ++ return ret; + } + + restored_client_t client_loc = (restored_client_t) malloc(sizeof(struct restored_client_private)); +@@ -321,7 +321,7 @@ LIBIMOBILEDEVICE_API restored_error_t restored_client_new(idevice_t device, rest + idev_ret = idevice_get_udid(device, &client_loc->udid); + if (IDEVICE_E_SUCCESS != idev_ret) { + debug_info("failed to get device udid."); +- ret = RESTORE_E_DEVICE_ERROR; ++ ret = RESTORE_E_UNKNOWN_ERROR; + } + debug_info("device udid: %s", client_loc->udid); + +-- +2.23.0 + + +From 8f96c52de2f9f35f361d29095190fc673db7d1c1 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Fri, 27 Sep 2019 12:52:03 +0200 +Subject: [PATCH 131/151] Make sure to handle timeout errors in device link + service and all depending services + +--- + include/libimobiledevice/mobilebackup.h | 20 +++--- + include/libimobiledevice/mobilebackup2.h | 12 ++-- + include/libimobiledevice/mobilesync.h | 14 ++-- + include/libimobiledevice/screenshotr.h | 18 ++--- + src/device_link_service.c | 91 +++++++++++++----------- + src/device_link_service.h | 22 +++--- + src/mobilebackup.c | 5 ++ + src/mobilebackup.h | 1 + + src/mobilebackup2.c | 6 +- + src/mobilebackup2.h | 2 +- + src/mobilesync.c | 4 ++ + src/screenshotr.c | 6 +- + 12 files changed, 117 insertions(+), 84 deletions(-) + +diff --git a/include/libimobiledevice/mobilebackup.h b/include/libimobiledevice/mobilebackup.h +index 6da3bed..f22150d 100644 +--- a/include/libimobiledevice/mobilebackup.h ++++ b/include/libimobiledevice/mobilebackup.h +@@ -3,8 +3,8 @@ + * @brief Backup and restore of all device data. + * \internal + * +- * Copyright (c) 2009-2014 Martin Szulecki All Rights Reserved. +- * Copyright (c) 2010 Nikias Bassen All Rights Reserved. ++ * Copyright (c) 2010-2019 Nikias Bassen, All Rights Reserved. ++ * Copyright (c) 2009-2014 Martin Szulecki, All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public +@@ -35,13 +35,15 @@ extern "C" { + + /** Error Codes */ + typedef enum { +- MOBILEBACKUP_E_SUCCESS = 0, +- MOBILEBACKUP_E_INVALID_ARG = -1, +- MOBILEBACKUP_E_PLIST_ERROR = -2, +- MOBILEBACKUP_E_MUX_ERROR = -3, +- MOBILEBACKUP_E_BAD_VERSION = -4, +- MOBILEBACKUP_E_REPLY_NOT_OK = -5, +- MOBILEBACKUP_E_UNKNOWN_ERROR = -256 ++ MOBILEBACKUP_E_SUCCESS = 0, ++ MOBILEBACKUP_E_INVALID_ARG = -1, ++ MOBILEBACKUP_E_PLIST_ERROR = -2, ++ MOBILEBACKUP_E_MUX_ERROR = -3, ++ MOBILEBACKUP_E_SSL_ERROR = -4, ++ MOBILEBACKUP_E_RECEIVE_TIMEOUT = -5, ++ MOBILEBACKUP_E_BAD_VERSION = -6, ++ MOBILEBACKUP_E_REPLY_NOT_OK = -7, ++ MOBILEBACKUP_E_UNKNOWN_ERROR = -256 + } mobilebackup_error_t; + + typedef struct mobilebackup_client_private mobilebackup_client_private; +diff --git a/include/libimobiledevice/mobilebackup2.h b/include/libimobiledevice/mobilebackup2.h +index 0c42334..239c807 100644 +--- a/include/libimobiledevice/mobilebackup2.h ++++ b/include/libimobiledevice/mobilebackup2.h +@@ -3,8 +3,8 @@ + * @brief Backup and restore of all device data (mobilebackup2, iOS4+ only) + * \internal + * +- * Copyright (c) 2011-2014 Martin Szulecki All Rights Reserved. +- * Copyright (c) 2010-2012 Nikias Bassen All Rights Reserved. ++ * Copyright (c) 2010-2019 Nikias Bassen, All Rights Reserved. ++ * Copyright (c) 2011-2014 Martin Szulecki, All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public +@@ -39,9 +39,11 @@ typedef enum { + MOBILEBACKUP2_E_INVALID_ARG = -1, + MOBILEBACKUP2_E_PLIST_ERROR = -2, + MOBILEBACKUP2_E_MUX_ERROR = -3, +- MOBILEBACKUP2_E_BAD_VERSION = -4, +- MOBILEBACKUP2_E_REPLY_NOT_OK = -5, +- MOBILEBACKUP2_E_NO_COMMON_VERSION = -6, ++ MOBILEBACKUP2_E_SSL_ERROR = -4, ++ MOBILEBACKUP2_E_RECEIVE_TIMEOUT = -5, ++ MOBILEBACKUP2_E_BAD_VERSION = -6, ++ MOBILEBACKUP2_E_REPLY_NOT_OK = -7, ++ MOBILEBACKUP2_E_NO_COMMON_VERSION = -8, + MOBILEBACKUP2_E_UNKNOWN_ERROR = -256 + } mobilebackup2_error_t; + +diff --git a/include/libimobiledevice/mobilesync.h b/include/libimobiledevice/mobilesync.h +index e6885c7..005ef3f 100644 +--- a/include/libimobiledevice/mobilesync.h ++++ b/include/libimobiledevice/mobilesync.h +@@ -3,8 +3,8 @@ + * @brief Synchronize data classes with a device and computer. + * \internal + * ++ * Copyright (c) 2010-2019 Nikias Bassen, All Rights Reserved. + * Copyright (c) 2010-2014 Martin Szulecki All Rights Reserved. +- * Copyright (c) 2010-2011 Nikias Bassen All Rights Reserved. + * Copyright (c) 2014 Christophe Fergeau All Rights Reserved. + * Copyright (c) 2010 Bryan Forbes All Rights Reserved. + * Copyright (c) 2009 Jonathan Beck All Rights Reserved. +@@ -42,11 +42,13 @@ typedef enum { + MOBILESYNC_E_INVALID_ARG = -1, + MOBILESYNC_E_PLIST_ERROR = -2, + MOBILESYNC_E_MUX_ERROR = -3, +- MOBILESYNC_E_BAD_VERSION = -4, +- MOBILESYNC_E_SYNC_REFUSED = -5, +- MOBILESYNC_E_CANCELLED = -6, +- MOBILESYNC_E_WRONG_DIRECTION = -7, +- MOBILESYNC_E_NOT_READY = -8, ++ MOBILESYNC_E_SSL_ERROR = -4, ++ MOBILESYNC_E_RECEIVE_TIMEOUT = -5, ++ MOBILESYNC_E_BAD_VERSION = -6, ++ MOBILESYNC_E_SYNC_REFUSED = -7, ++ MOBILESYNC_E_CANCELLED = -8, ++ MOBILESYNC_E_WRONG_DIRECTION = -9, ++ MOBILESYNC_E_NOT_READY = -10, + MOBILESYNC_E_UNKNOWN_ERROR = -256 + } mobilesync_error_t; + +diff --git a/include/libimobiledevice/screenshotr.h b/include/libimobiledevice/screenshotr.h +index c12646b..83ca96b 100644 +--- a/include/libimobiledevice/screenshotr.h ++++ b/include/libimobiledevice/screenshotr.h +@@ -4,8 +4,8 @@ + * @note Requires a mounted developer image. + * \internal + * +- * Copyright (c) 2010-2014 Martin Szulecki All Rights Reserved. +- * Copyright (c) 2010 Nikias Bassen All Rights Reserved. ++ * Copyright (c) 2010-2019 Nikias Bassen, All Rights Reserved. ++ * Copyright (c) 2010-2014 Martin Szulecki, All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public +@@ -36,12 +36,14 @@ extern "C" { + + /** Error Codes */ + typedef enum { +- SCREENSHOTR_E_SUCCESS = 0, +- SCREENSHOTR_E_INVALID_ARG = -1, +- SCREENSHOTR_E_PLIST_ERROR = -2, +- SCREENSHOTR_E_MUX_ERROR = -3, +- SCREENSHOTR_E_BAD_VERSION = -4, +- SCREENSHOTR_E_UNKNOWN_ERROR = -256 ++ SCREENSHOTR_E_SUCCESS = 0, ++ SCREENSHOTR_E_INVALID_ARG = -1, ++ SCREENSHOTR_E_PLIST_ERROR = -2, ++ SCREENSHOTR_E_MUX_ERROR = -3, ++ SCREENSHOTR_E_SSL_ERROR = -4, ++ SCREENSHOTR_E_RECEIVE_TIMEOUT = -5, ++ SCREENSHOTR_E_BAD_VERSION = -6, ++ SCREENSHOTR_E_UNKNOWN_ERROR = -256 + } screenshotr_error_t; + + typedef struct screenshotr_client_private screenshotr_client_private; +diff --git a/src/device_link_service.c b/src/device_link_service.c +index 007223e..856d301 100644 +--- a/src/device_link_service.c ++++ b/src/device_link_service.c +@@ -2,7 +2,7 @@ + * device_link_service.c + * DeviceLink service implementation. + * +- * Copyright (c) 2010 Nikias Bassen, All Rights Reserved. ++ * Copyright (c) 2010-2019 Nikias Bassen, All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public +@@ -24,6 +24,27 @@ + #include "property_list_service.h" + #include "common/debug.h" + ++static device_link_service_error_t device_link_error(property_list_service_error_t err) ++{ ++ switch (err) { ++ case PROPERTY_LIST_SERVICE_E_SUCCESS: ++ return DEVICE_LINK_SERVICE_E_SUCCESS; ++ case PROPERTY_LIST_SERVICE_E_INVALID_ARG: ++ return DEVICE_LINK_SERVICE_E_INVALID_ARG; ++ case PROPERTY_LIST_SERVICE_E_PLIST_ERROR: ++ return DEVICE_LINK_SERVICE_E_PLIST_ERROR; ++ case PROPERTY_LIST_SERVICE_E_MUX_ERROR: ++ return DEVICE_LINK_SERVICE_E_MUX_ERROR; ++ case PROPERTY_LIST_SERVICE_E_SSL_ERROR: ++ return DEVICE_LINK_SERVICE_E_SSL_ERROR; ++ case PROPERTY_LIST_SERVICE_E_RECEIVE_TIMEOUT: ++ return DEVICE_LINK_SERVICE_E_RECEIVE_TIMEOUT; ++ default: ++ break; ++ } ++ return DEVICE_LINK_SERVICE_E_UNKNOWN_ERROR; ++} ++ + /** + * Internally used function to extract the message string from a DL* message + * plist. +@@ -89,18 +110,15 @@ device_link_service_error_t device_link_service_client_new(idevice_t device, loc + } + + property_list_service_client_t plistclient = NULL; +- if (property_list_service_client_new(device, service, &plistclient) != PROPERTY_LIST_SERVICE_E_SUCCESS) { +- return DEVICE_LINK_SERVICE_E_MUX_ERROR; ++ device_link_service_error_t err = device_link_error(property_list_service_client_new(device, service, &plistclient)); ++ if (err != DEVICE_LINK_SERVICE_E_SUCCESS) { ++ return err; + } + + /* create client object */ + device_link_service_client_t client_loc = (device_link_service_client_t) malloc(sizeof(struct device_link_service_client_private)); + client_loc->parent = plistclient; + +- /* enable SSL if requested */ +- if (service->ssl_enabled) +- property_list_service_enable_ssl(client_loc->parent); +- + /* all done, return success */ + *client = client_loc; + return DEVICE_LINK_SERVICE_E_SUCCESS; +@@ -121,11 +139,10 @@ device_link_service_error_t device_link_service_client_free(device_link_service_ + if (!client) + return DEVICE_LINK_SERVICE_E_INVALID_ARG; + +- if (property_list_service_client_free(client->parent) != PROPERTY_LIST_SERVICE_E_SUCCESS) { +- return DEVICE_LINK_SERVICE_E_UNKNOWN_ERROR; +- } ++ device_link_service_error_t err = device_link_error(property_list_service_client_free(client->parent)); + free(client); +- return DEVICE_LINK_SERVICE_E_SUCCESS; ++ ++ return err; + } + + /** +@@ -157,9 +174,9 @@ device_link_service_error_t device_link_service_version_exchange(device_link_ser + char *msg = NULL; + + /* receive DLMessageVersionExchange from device */ +- if (property_list_service_receive_plist(client->parent, &array) != PROPERTY_LIST_SERVICE_E_SUCCESS) { ++ err = device_link_error(property_list_service_receive_plist(client->parent, &array)); ++ if (err != DEVICE_LINK_SERVICE_E_SUCCESS) { + debug_info("Did not receive initial message from device!"); +- err = DEVICE_LINK_SERVICE_E_MUX_ERROR; + goto leave; + } + device_link_service_get_message(array, &msg); +@@ -203,18 +220,18 @@ device_link_service_error_t device_link_service_version_exchange(device_link_ser + plist_array_append_item(array, plist_new_string("DLMessageVersionExchange")); + plist_array_append_item(array, plist_new_string("DLVersionsOk")); + plist_array_append_item(array, plist_new_uint(version_major)); +- if (property_list_service_send_binary_plist(client->parent, array) != PROPERTY_LIST_SERVICE_E_SUCCESS) { ++ err = device_link_error(property_list_service_send_binary_plist(client->parent, array)); ++ if (err != DEVICE_LINK_SERVICE_E_SUCCESS) { + debug_info("Error when sending DLVersionsOk"); +- err = DEVICE_LINK_SERVICE_E_MUX_ERROR; + goto leave; + } + plist_free(array); + + /* receive DeviceReady message */ + array = NULL; +- if (property_list_service_receive_plist(client->parent, &array) != PROPERTY_LIST_SERVICE_E_SUCCESS) { ++ err = device_link_error(property_list_service_receive_plist(client->parent, &array)); ++ if (err != DEVICE_LINK_SERVICE_E_SUCCESS) { + debug_info("Error when receiving DLMessageDeviceReady!"); +- err = DEVICE_LINK_SERVICE_E_MUX_ERROR; + goto leave; + } + device_link_service_get_message(array, &msg); +@@ -258,11 +275,9 @@ device_link_service_error_t device_link_service_disconnect(device_link_service_c + else + plist_array_append_item(array, plist_new_string("___EmptyParameterString___")); + +- device_link_service_error_t err = DEVICE_LINK_SERVICE_E_SUCCESS; +- if (property_list_service_send_binary_plist(client->parent, array) != PROPERTY_LIST_SERVICE_E_SUCCESS) { +- err = DEVICE_LINK_SERVICE_E_MUX_ERROR; +- } ++ device_link_service_error_t err = device_link_error(property_list_service_send_binary_plist(client->parent, array)); + plist_free(array); ++ + return err; + } + +@@ -286,11 +301,9 @@ device_link_service_error_t device_link_service_send_ping(device_link_service_cl + plist_array_append_item(array, plist_new_string("DLMessagePing")); + plist_array_append_item(array, plist_new_string(message)); + +- device_link_service_error_t err = DEVICE_LINK_SERVICE_E_SUCCESS; +- if (property_list_service_send_binary_plist(client->parent, array) != PROPERTY_LIST_SERVICE_E_SUCCESS) { +- err = DEVICE_LINK_SERVICE_E_MUX_ERROR; +- } ++ device_link_service_error_t err = device_link_error(property_list_service_send_binary_plist(client->parent, array)); + plist_free(array); ++ + return err; + } + +@@ -317,11 +330,9 @@ device_link_service_error_t device_link_service_send_process_message(device_link + plist_array_append_item(array, plist_new_string("DLMessageProcessMessage")); + plist_array_append_item(array, plist_copy(message)); + +- device_link_service_error_t err = DEVICE_LINK_SERVICE_E_SUCCESS; +- if (property_list_service_send_binary_plist(client->parent, array) != PROPERTY_LIST_SERVICE_E_SUCCESS) { +- err = DEVICE_LINK_SERVICE_E_MUX_ERROR; +- } ++ device_link_service_error_t err = device_link_error(property_list_service_send_binary_plist(client->parent, array)); + plist_free(array); ++ + return err; + } + +@@ -348,8 +359,9 @@ device_link_service_error_t device_link_service_receive_message(device_link_serv + return DEVICE_LINK_SERVICE_E_INVALID_ARG; + + *msg_plist = NULL; +- if (property_list_service_receive_plist(client->parent, msg_plist) != PROPERTY_LIST_SERVICE_E_SUCCESS) { +- return DEVICE_LINK_SERVICE_E_MUX_ERROR; ++ device_link_service_error_t err = device_link_error(property_list_service_receive_plist(client->parent, msg_plist)); ++ if (err != DEVICE_LINK_SERVICE_E_SUCCESS) { ++ return err; + } + + if (!device_link_service_get_message(*msg_plist, dlmessage)) { +@@ -378,11 +390,12 @@ device_link_service_error_t device_link_service_receive_process_message(device_l + return DEVICE_LINK_SERVICE_E_INVALID_ARG; + + plist_t pmsg = NULL; +- if (property_list_service_receive_plist(client->parent, &pmsg) != PROPERTY_LIST_SERVICE_E_SUCCESS) { +- return DEVICE_LINK_SERVICE_E_MUX_ERROR; ++ device_link_service_error_t err = device_link_error(property_list_service_receive_plist(client->parent, &pmsg)); ++ if (err != DEVICE_LINK_SERVICE_E_SUCCESS) { ++ return err; + } + +- device_link_service_error_t err = DEVICE_LINK_SERVICE_E_UNKNOWN_ERROR; ++ err = DEVICE_LINK_SERVICE_E_UNKNOWN_ERROR; + + char *msg = NULL; + device_link_service_get_message(pmsg, &msg); +@@ -432,10 +445,7 @@ device_link_service_error_t device_link_service_send(device_link_service_client_ + if (!client || !plist) { + return DEVICE_LINK_SERVICE_E_INVALID_ARG; + } +- if (property_list_service_send_binary_plist(client->parent, plist) != PROPERTY_LIST_SERVICE_E_SUCCESS) { +- return DEVICE_LINK_SERVICE_E_MUX_ERROR; +- } +- return DEVICE_LINK_SERVICE_E_SUCCESS; ++ return device_link_error(property_list_service_send_binary_plist(client->parent, plist)); + } + + /* Generic device link service receive function. +@@ -455,9 +465,6 @@ device_link_service_error_t device_link_service_receive(device_link_service_clie + return DEVICE_LINK_SERVICE_E_INVALID_ARG; + } + +- if (property_list_service_receive_plist(client->parent, plist) != PROPERTY_LIST_SERVICE_E_SUCCESS) { +- return DEVICE_LINK_SERVICE_E_MUX_ERROR; +- } +- return DEVICE_LINK_SERVICE_E_SUCCESS; ++ return device_link_error(property_list_service_receive_plist(client->parent, plist)); + } + +diff --git a/src/device_link_service.h b/src/device_link_service.h +index a0c8390..eae912a 100644 +--- a/src/device_link_service.h ++++ b/src/device_link_service.h +@@ -2,7 +2,7 @@ + * device_link_service.h + * Definitions for the DeviceLink service + * +- * Copyright (c) 2010 Nikias Bassen, All Rights Reserved. ++ * Copyright (c) 2010-2019 Nikias Bassen, All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public +@@ -25,16 +25,16 @@ + #include "property_list_service.h" + + /* Error Codes */ +-#define DEVICE_LINK_SERVICE_E_SUCCESS 0 +-#define DEVICE_LINK_SERVICE_E_INVALID_ARG -1 +-#define DEVICE_LINK_SERVICE_E_PLIST_ERROR -2 +-#define DEVICE_LINK_SERVICE_E_MUX_ERROR -3 +-#define DEVICE_LINK_SERVICE_E_BAD_VERSION -4 +- +-#define DEVICE_LINK_SERVICE_E_UNKNOWN_ERROR -256 +- +-/** Represents an error code. */ +-typedef int16_t device_link_service_error_t; ++typedef enum { ++ DEVICE_LINK_SERVICE_E_SUCCESS = 0, ++ DEVICE_LINK_SERVICE_E_INVALID_ARG = -1, ++ DEVICE_LINK_SERVICE_E_PLIST_ERROR = -2, ++ DEVICE_LINK_SERVICE_E_MUX_ERROR = -3, ++ DEVICE_LINK_SERVICE_E_SSL_ERROR = -4, ++ DEVICE_LINK_SERVICE_E_RECEIVE_TIMEOUT = -5, ++ DEVICE_LINK_SERVICE_E_BAD_VERSION = -6, ++ DEVICE_LINK_SERVICE_E_UNKNOWN_ERROR = -256 ++} device_link_service_error_t; + + struct device_link_service_client_private { + property_list_service_client_t parent; +diff --git a/src/mobilebackup.c b/src/mobilebackup.c +index b32e0ba..2682a6f 100644 +--- a/src/mobilebackup.c ++++ b/src/mobilebackup.c +@@ -2,6 +2,7 @@ + * mobilebackup.c + * Contains functions for the built-in MobileBackup client. + * ++ * Copyright (c) 2010-2019 Nikias Bassen, All Rights Reserved. + * Copyright (c) 2009 Martin Szulecki All Rights Reserved. + * + * This library is free software; you can redistribute it and/or +@@ -52,6 +53,10 @@ static mobilebackup_error_t mobilebackup_error(device_link_service_error_t err) + return MOBILEBACKUP_E_PLIST_ERROR; + case DEVICE_LINK_SERVICE_E_MUX_ERROR: + return MOBILEBACKUP_E_MUX_ERROR; ++ case DEVICE_LINK_SERVICE_E_SSL_ERROR: ++ return MOBILEBACKUP_E_SSL_ERROR; ++ case DEVICE_LINK_SERVICE_E_RECEIVE_TIMEOUT: ++ return MOBILEBACKUP_E_RECEIVE_TIMEOUT; + case DEVICE_LINK_SERVICE_E_BAD_VERSION: + return MOBILEBACKUP_E_BAD_VERSION; + default: +diff --git a/src/mobilebackup.h b/src/mobilebackup.h +index 19b9999..edda70f 100644 +--- a/src/mobilebackup.h ++++ b/src/mobilebackup.h +@@ -2,6 +2,7 @@ + * mobilebackup.h + * Definitions for the mobilebackup service + * ++ * Copyright (c) 2010-2019 Nikias Bassen, All Rights Reserved. + * Copyright (c) 2009 Martin Szulecki All Rights Reserved. + * + * This library is free software; you can redistribute it and/or +diff --git a/src/mobilebackup2.c b/src/mobilebackup2.c +index 08ce22b..e7cc581 100644 +--- a/src/mobilebackup2.c ++++ b/src/mobilebackup2.c +@@ -2,7 +2,7 @@ + * mobilebackup2.c + * Contains functions for the built-in MobileBackup2 client (iOS4+ only) + * +- * Copyright (c) 2010 Nikias Bassen All Rights Reserved. ++ * Copyright (c) 2010-2019 Nikias Bassen, All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public +@@ -53,6 +53,10 @@ static mobilebackup2_error_t mobilebackup2_error(device_link_service_error_t err + return MOBILEBACKUP2_E_PLIST_ERROR; + case DEVICE_LINK_SERVICE_E_MUX_ERROR: + return MOBILEBACKUP2_E_MUX_ERROR; ++ case DEVICE_LINK_SERVICE_E_SSL_ERROR: ++ return MOBILEBACKUP2_E_SSL_ERROR; ++ case DEVICE_LINK_SERVICE_E_RECEIVE_TIMEOUT: ++ return MOBILEBACKUP2_E_RECEIVE_TIMEOUT; + case DEVICE_LINK_SERVICE_E_BAD_VERSION: + return MOBILEBACKUP2_E_BAD_VERSION; + default: +diff --git a/src/mobilebackup2.h b/src/mobilebackup2.h +index 4dba22a..025b6bf 100644 +--- a/src/mobilebackup2.h ++++ b/src/mobilebackup2.h +@@ -2,7 +2,7 @@ + * mobilebackup2.h + * Definitions for the mobilebackup2 service (iOS4+) + * +- * Copyright (c) 2010 Nikias Bassen All Rights Reserved. ++ * Copyright (c) 2010-2019 Nikias Bassen, All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public +diff --git a/src/mobilesync.c b/src/mobilesync.c +index d903cfe..b0efc80 100644 +--- a/src/mobilesync.c ++++ b/src/mobilesync.c +@@ -57,6 +57,10 @@ static mobilesync_error_t mobilesync_error(device_link_service_error_t err) + return MOBILESYNC_E_PLIST_ERROR; + case DEVICE_LINK_SERVICE_E_MUX_ERROR: + return MOBILESYNC_E_MUX_ERROR; ++ case DEVICE_LINK_SERVICE_E_SSL_ERROR: ++ return MOBILESYNC_E_SSL_ERROR; ++ case DEVICE_LINK_SERVICE_E_RECEIVE_TIMEOUT: ++ return MOBILESYNC_E_RECEIVE_TIMEOUT; + case DEVICE_LINK_SERVICE_E_BAD_VERSION: + return MOBILESYNC_E_BAD_VERSION; + default: +diff --git a/src/screenshotr.c b/src/screenshotr.c +index 5c4a53f..ddb9d6e 100644 +--- a/src/screenshotr.c ++++ b/src/screenshotr.c +@@ -2,7 +2,7 @@ + * screenshotr.c + * com.apple.mobile.screenshotr service implementation. + * +- * Copyright (c) 2010 Nikias Bassen All Rights Reserved. ++ * Copyright (c) 2010-2019 Nikias Bassen, All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public +@@ -50,6 +50,10 @@ static screenshotr_error_t screenshotr_error(device_link_service_error_t err) + return SCREENSHOTR_E_PLIST_ERROR; + case DEVICE_LINK_SERVICE_E_MUX_ERROR: + return SCREENSHOTR_E_MUX_ERROR; ++ case DEVICE_LINK_SERVICE_E_SSL_ERROR: ++ return SCREENSHOTR_E_SSL_ERROR; ++ case DEVICE_LINK_SERVICE_E_RECEIVE_TIMEOUT: ++ return SCREENSHOTR_E_RECEIVE_TIMEOUT; + case DEVICE_LINK_SERVICE_E_BAD_VERSION: + return SCREENSHOTR_E_BAD_VERSION; + default: +-- +2.23.0 + + +From 7e06820721be573b625921da86f736a89989d023 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Fri, 27 Sep 2019 13:48:54 +0200 +Subject: [PATCH 132/151] idevicebackup2: Handle timeout vs. error condition in + main loop + +--- + tools/idevicebackup2.c | 16 ++++++++++------ + 1 file changed, 10 insertions(+), 6 deletions(-) + +diff --git a/tools/idevicebackup2.c b/tools/idevicebackup2.c +index 58fda8d..1ac5d1a 100644 +--- a/tools/idevicebackup2.c ++++ b/tools/idevicebackup2.c +@@ -2,8 +2,8 @@ + * idevicebackup2.c + * Command line interface to use the device's backup and restore service + * +- * Copyright (c) 2010-2018 Nikias Bassen All Rights Reserved. +- * Copyright (c) 2009-2010 Martin Szulecki All Rights Reserved. ++ * Copyright (c) 2010-2019 Nikias Bassen, All Rights Reserved. ++ * Copyright (c) 2009-2010 Martin Szulecki, All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public +@@ -2128,6 +2128,7 @@ checkpoint: + int operation_ok = 0; + plist_t message = NULL; + ++ mobilebackup2_error_t mberr; + char *dlmsg = NULL; + int file_count = 0; + int errcode = 0; +@@ -2138,10 +2139,13 @@ checkpoint: + do { + free(dlmsg); + dlmsg = NULL; +- mobilebackup2_receive_message(mobilebackup2, &message, &dlmsg); +- if (!message || !dlmsg) { +- PRINT_VERBOSE(1, "Device is not ready yet. Going to try again in 2 seconds...\n"); +- sleep(2); ++ mberr = mobilebackup2_receive_message(mobilebackup2, &message, &dlmsg); ++ if (mberr == MOBILEBACKUP2_E_RECEIVE_TIMEOUT) { ++ PRINT_VERBOSE(2, "Device is not ready yet, retrying...\n"); ++ goto files_out; ++ } else if (mberr != MOBILEBACKUP2_E_SUCCESS) { ++ PRINT_VERBOSE(0, "ERROR: Could not receive from mobilebackup2 (%d)\n", mberr); ++ quit_flag++; + goto files_out; + } + +-- +2.23.0 + + +From 1faa16c912dd5eb4e9305b25b13407de195ad103 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Fri, 27 Sep 2019 19:16:46 +0200 +Subject: [PATCH 133/151] idevicebackup2: Add passcode hint when + enabling/disabling backup encryption or change the password + +--- + tools/idevicebackup2.c | 48 ++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 48 insertions(+) + +diff --git a/tools/idevicebackup2.c b/tools/idevicebackup2.c +index 1ac5d1a..3a4de67 100644 +--- a/tools/idevicebackup2.c ++++ b/tools/idevicebackup2.c +@@ -42,6 +42,7 @@ + #include + #include + #include ++#include + #include "common/utils.h" + + #include +@@ -1433,6 +1434,8 @@ static void print_usage(int argc, char **argv) + printf("Homepage: <" PACKAGE_URL ">\n"); + } + ++#define DEVICE_VERSION(maj, min, patch) (((maj & 0xFF) << 16) | ((min & 0xFF) << 8) | (patch & 0xFF)) ++ + int main(int argc, char *argv[]) + { + idevice_error_t ret = IDEVICE_E_UNKNOWN_ERROR; +@@ -1757,6 +1760,25 @@ int main(int argc, char *argv[]) + node_tmp = NULL; + } + ++ /* get ProductVersion */ ++ char *product_version = NULL; ++ int device_version = 0; ++ node_tmp = NULL; ++ lockdownd_get_value(lockdown, NULL, "ProductVersion", &node_tmp); ++ if (node_tmp) { ++ if (plist_get_node_type(node_tmp) == PLIST_STRING) { ++ plist_get_string_val(node_tmp, &product_version); ++ } ++ plist_free(node_tmp); ++ node_tmp = NULL; ++ } ++ if (product_version) { ++ int vers[3] = { 0, 0, 0 }; ++ if (sscanf(product_version, "%d.%d.%d", &vers[0], &vers[1], &vers[2]) >= 2) { ++ device_version = DEVICE_VERSION(vers[0], vers[1], vers[2]); ++ } ++ } ++ + /* start notification_proxy */ + np_client_t np = NULL; + ldret = lockdownd_start_service(lockdown, NP_SERVICE_NAME, &service); +@@ -2108,6 +2130,32 @@ checkpoint: + } + if (newpw || backup_password) { + mobilebackup2_send_message(mobilebackup2, "ChangePassword", opts); ++ uint8_t passcode_hint = 0; ++ if (device_version >= DEVICE_VERSION(13,0,0)) { ++ diagnostics_relay_client_t diag = NULL; ++ if (diagnostics_relay_client_start_service(device, &diag, "idevicebackup2") == DIAGNOSTICS_RELAY_E_SUCCESS) { ++ plist_t dict = NULL; ++ plist_t keys = plist_new_array(); ++ plist_array_append_item(keys, plist_new_string("PasswordConfigured")); ++ if (diagnostics_relay_query_mobilegestalt(diag, keys, &dict) == DIAGNOSTICS_RELAY_E_SUCCESS) { ++ plist_t node = plist_access_path(dict, 2, "MobileGestalt", "PasswordConfigured"); ++ plist_get_bool_val(node, &passcode_hint); ++ } ++ plist_free(keys); ++ plist_free(dict); ++ diagnostics_relay_goodbye(diag); ++ diagnostics_relay_client_free(diag); ++ } ++ } ++ if (passcode_hint) { ++ if (cmd_flags & CMD_FLAG_ENCRYPTION_CHANGEPW) { ++ PRINT_VERBOSE(1, "Please confirm changing the backup password by entering the passcode on the device.\n"); ++ } else if (cmd_flags & CMD_FLAG_ENCRYPTION_ENABLE) { ++ PRINT_VERBOSE(1, "Please confirm enabling the backup encryption by entering the passcode on the device.\n"); ++ } else if (cmd_flags & CMD_FLAG_ENCRYPTION_DISABLE) { ++ PRINT_VERBOSE(1, "Please confirm disabling the backup encryption by entering the passcode on the device.\n"); ++ } ++ } + /*if (cmd_flags & CMD_FLAG_ENCRYPTION_ENABLE) { + int retr = 10; + while ((retr-- >= 0) && !backup_domain_changed) { +-- +2.23.0 + + +From 92d95d0b8f1870d7cc9eb809a993b04b0e733205 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Fri, 27 Sep 2019 20:44:03 +0200 +Subject: [PATCH 134/151] mobile_image_mounter: Better error handling (e.g. + when device is locked) + +--- + .../libimobiledevice/mobile_image_mounter.h | 1 + + src/mobile_image_mounter.c | 77 ++++++++++--------- + tools/ideviceimagemounter.c | 13 +++- + 3 files changed, 53 insertions(+), 38 deletions(-) + +diff --git a/include/libimobiledevice/mobile_image_mounter.h b/include/libimobiledevice/mobile_image_mounter.h +index 8d783c4..e185ad5 100644 +--- a/include/libimobiledevice/mobile_image_mounter.h ++++ b/include/libimobiledevice/mobile_image_mounter.h +@@ -40,6 +40,7 @@ typedef enum { + MOBILE_IMAGE_MOUNTER_E_PLIST_ERROR = -2, + MOBILE_IMAGE_MOUNTER_E_CONN_FAILED = -3, + MOBILE_IMAGE_MOUNTER_E_COMMAND_FAILED = -4, ++ MOBILE_IMAGE_MOUNTER_E_DEVICE_LOCKED = -5, + MOBILE_IMAGE_MOUNTER_E_UNKNOWN_ERROR = -256 + } mobile_image_mounter_error_t; + +diff --git a/src/mobile_image_mounter.c b/src/mobile_image_mounter.c +index c8c4c6f..bbebbb4 100644 +--- a/src/mobile_image_mounter.c ++++ b/src/mobile_image_mounter.c +@@ -2,7 +2,7 @@ + * mobile_image_mounter.c + * com.apple.mobile.mobile_image_mounter service implementation. + * +- * Copyright (c) 2010 Nikias Bassen, All Rights Reserved. ++ * Copyright (c) 2010-2019 Nikias Bassen, All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public +@@ -141,6 +141,43 @@ leave_unlock: + return res; + } + ++static mobile_image_mounter_error_t process_result(plist_t result, const char *expected_status) ++{ ++ mobile_image_mounter_error_t res = MOBILE_IMAGE_MOUNTER_E_COMMAND_FAILED; ++ char* strval = NULL; ++ plist_t node; ++ ++ node = plist_dict_get_item(result, "Error"); ++ if (node && plist_get_node_type(node) == PLIST_STRING) { ++ plist_get_string_val(node, &strval); ++ } ++ if (strval) { ++ if (!strcmp(strval, "DeviceLocked")) { ++ debug_info("Device is locked, can't mount"); ++ res = MOBILE_IMAGE_MOUNTER_E_DEVICE_LOCKED; ++ } else { ++ debug_info("Unhandled error '%s' received", strval); ++ } ++ free(strval); ++ return res; ++ } ++ ++ node = plist_dict_get_item(result, "Status"); ++ if (node && plist_get_node_type(node) == PLIST_STRING) { ++ plist_get_string_val(node, &strval); ++ } ++ if (!strval) { ++ debug_info("Error: Unexpected response received!"); ++ } else if (strcmp(strval, expected_status) == 0) { ++ res = MOBILE_IMAGE_MOUNTER_E_SUCCESS; ++ } else { ++ debug_info("Error: didn't get %s but %s", expected_status, strval); ++ } ++ free(strval); ++ ++ return res; ++} ++ + LIBIMOBILEDEVICE_API mobile_image_mounter_error_t mobile_image_mounter_upload_image(mobile_image_mounter_client_t client, const char *image_type, size_t image_size, const char *signature, uint16_t signature_size, mobile_image_mounter_upload_cb_t upload_cb, void* userdata) + { + if (!client || !image_type || (image_size == 0) || !upload_cb) { +@@ -169,23 +206,10 @@ LIBIMOBILEDEVICE_API mobile_image_mounter_error_t mobile_image_mounter_upload_im + debug_info("Error receiving response from device!"); + goto leave_unlock; + } +- res = MOBILE_IMAGE_MOUNTER_E_COMMAND_FAILED; +- +- char* strval = NULL; +- plist_t node = plist_dict_get_item(result, "Status"); +- if (node && plist_get_node_type(node) == PLIST_STRING) { +- plist_get_string_val(node, &strval); +- } +- if (!strval) { +- debug_info("Error: Unexpected response received!"); +- goto leave_unlock; +- } +- if (strcmp(strval, "ReceiveBytesAck") != 0) { +- debug_info("Error: didn't get ReceiveBytesAck but %s", strval); +- free(strval); ++ res = process_result(result, "ReceiveBytesAck"); ++ if (res != MOBILE_IMAGE_MOUNTER_E_SUCCESS) { + goto leave_unlock; + } +- free(strval); + + size_t tx = 0; + size_t bufsize = 65536; +@@ -223,26 +247,7 @@ LIBIMOBILEDEVICE_API mobile_image_mounter_error_t mobile_image_mounter_upload_im + debug_info("Error receiving response from device!"); + goto leave_unlock; + } +- res = MOBILE_IMAGE_MOUNTER_E_COMMAND_FAILED; +- +- strval = NULL; +- node = plist_dict_get_item(result, "Status"); +- if (node && plist_get_node_type(node) == PLIST_STRING) { +- plist_get_string_val(node, &strval); +- } +- if (!strval) { +- debug_info("Error: Unexpected response received!"); +- goto leave_unlock; +- } +- if (strcmp(strval, "Complete") != 0) { +- debug_info("Error: didn't get Complete but %s", strval); +- free(strval); +- goto leave_unlock; +- } else { +- res = MOBILE_IMAGE_MOUNTER_E_SUCCESS; +- } +- free(strval); +- ++ res = process_result(result, "Complete"); + + leave_unlock: + mobile_image_mounter_unlock(client); +diff --git a/tools/ideviceimagemounter.c b/tools/ideviceimagemounter.c +index 7101c7e..93cab09 100644 +--- a/tools/ideviceimagemounter.c ++++ b/tools/ideviceimagemounter.c +@@ -248,7 +248,7 @@ int main(int argc, char **argv) + lockdownd_client_free(lckd); + lckd = NULL; + +- mobile_image_mounter_error_t err; ++ mobile_image_mounter_error_t err = MOBILE_IMAGE_MOUNTER_E_UNKNOWN_ERROR; + plist_t result = NULL; + + if (list_mode) { +@@ -344,7 +344,7 @@ int main(int argc, char **argv) + uint32_t written, total = 0; + while (total < amount) { + written = 0; +- if (afc_file_write(afc, af, buf, amount, &written) != ++ if (afc_file_write(afc, af, buf + total, amount - total, &written) != + AFC_E_SUCCESS) { + fprintf(stderr, "AFC Write error!\n"); + break; +@@ -368,6 +368,14 @@ int main(int argc, char **argv) + + fclose(f); + ++ if (err != MOBILE_IMAGE_MOUNTER_E_SUCCESS) { ++ if (err == MOBILE_IMAGE_MOUNTER_E_DEVICE_LOCKED) { ++ printf("ERROR: Device is locked, can't mount. Unlock device and try again.\n"); ++ } else { ++ printf("ERROR: Unknown error occurred, can't mount.\n"); ++ } ++ goto error_out; ++ } + printf("done.\n"); + + printf("Mounting...\n"); +@@ -435,6 +443,7 @@ int main(int argc, char **argv) + plist_free(result); + } + ++error_out: + /* perform hangup command */ + mobile_image_mounter_hangup(mim); + /* free client */ +-- +2.23.0 + + +From 8c7321b11512cc3cfd112ad2b4b65c5a81e12bba Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Sat, 28 Sep 2019 12:08:12 +0200 +Subject: [PATCH 135/151] tools: Ignore SIGPIPE wherever possible + +--- + tools/idevice_id.c | 7 +++++++ + tools/idevicecrashreport.c | 6 ++++++ + tools/idevicedate.c | 6 ++++++ + tools/idevicediagnostics.c | 6 ++++++ + tools/ideviceenterrecovery.c | 6 ++++++ + tools/ideviceimagemounter.c | 6 ++++++ + tools/ideviceinfo.c | 6 ++++++ + tools/idevicename.c | 7 +++++++ + tools/idevicepair.c | 6 ++++++ + tools/ideviceprovision.c | 6 ++++++ + tools/idevicescreenshot.c | 6 ++++++ + 11 files changed, 68 insertions(+) + +diff --git a/tools/idevice_id.c b/tools/idevice_id.c +index 558dcbe..8d888c0 100644 +--- a/tools/idevice_id.c ++++ b/tools/idevice_id.c +@@ -26,6 +26,10 @@ + #include + #include + #include ++#ifndef WIN32 ++#include ++#endif ++ + #include + #include + +@@ -60,6 +64,9 @@ int main(int argc, char **argv) + int mode = MODE_SHOW_ID; + const char* udid = NULL; + ++#ifndef WIN32 ++ signal(SIGPIPE, SIG_IGN); ++#endif + /* parse cmdline args */ + for (i = 1; i < argc; i++) { + if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")) { +diff --git a/tools/idevicecrashreport.c b/tools/idevicecrashreport.c +index 533265c..5d2e21d 100644 +--- a/tools/idevicecrashreport.c ++++ b/tools/idevicecrashreport.c +@@ -28,6 +28,9 @@ + #include + #include + #include ++#ifndef WIN32 ++#include ++#endif + #include "common/utils.h" + + #include +@@ -322,6 +325,9 @@ int main(int argc, char* argv[]) + int i; + const char* udid = NULL; + ++#ifndef WIN32 ++ signal(SIGPIPE, SIG_IGN); ++#endif + /* parse cmdline args */ + for (i = 1; i < argc; i++) { + if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")) { +diff --git a/tools/idevicedate.c b/tools/idevicedate.c +index 2676880..4de90b6 100644 +--- a/tools/idevicedate.c ++++ b/tools/idevicedate.c +@@ -30,6 +30,9 @@ + #if HAVE_LANGINFO_CODESET + #include + #endif ++#ifndef WIN32 ++#include ++#endif + + #include + #include +@@ -76,6 +79,9 @@ int main(int argc, char *argv[]) + char buffer[80]; + int result = 0; + ++#ifndef WIN32 ++ signal(SIGPIPE, SIG_IGN); ++#endif + /* parse cmdline args */ + for (i = 1; i < argc; i++) { + if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")) { +diff --git a/tools/idevicediagnostics.c b/tools/idevicediagnostics.c +index 08e7c5e..bff1e1d 100644 +--- a/tools/idevicediagnostics.c ++++ b/tools/idevicediagnostics.c +@@ -28,6 +28,9 @@ + #include + #include + #include ++#ifndef WIN32 ++#include ++#endif + + #include + #include +@@ -71,6 +74,9 @@ int main(int argc, char **argv) + plist_t node = NULL; + plist_t keys = NULL; + ++#ifndef WIN32 ++ signal(SIGPIPE, SIG_IGN); ++#endif + /* parse cmdline args */ + for (i = 1; i < argc; i++) { + if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")) { +diff --git a/tools/ideviceenterrecovery.c b/tools/ideviceenterrecovery.c +index 69484cc..ec9093b 100644 +--- a/tools/ideviceenterrecovery.c ++++ b/tools/ideviceenterrecovery.c +@@ -27,6 +27,9 @@ + #include + #include + #include ++#ifndef WIN32 ++#include ++#endif + + #include + #include +@@ -53,6 +56,9 @@ int main(int argc, char *argv[]) + int i; + const char* udid = NULL; + ++#ifndef WIN32 ++ signal(SIGPIPE, SIG_IGN); ++#endif + /* parse cmdline args */ + for (i = 1; i < argc; i++) { + if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")) { +diff --git a/tools/ideviceimagemounter.c b/tools/ideviceimagemounter.c +index 93cab09..74df5e4 100644 +--- a/tools/ideviceimagemounter.c ++++ b/tools/ideviceimagemounter.c +@@ -34,6 +34,9 @@ + #include + #include + #include ++#ifndef WIN32 ++#include ++#endif + + #include + #include +@@ -153,6 +156,9 @@ int main(int argc, char **argv) + size_t image_size = 0; + char *image_sig_path = NULL; + ++#ifndef WIN32 ++ signal(SIGPIPE, SIG_IGN); ++#endif + parse_opts(argc, argv); + + argc -= optind; +diff --git a/tools/ideviceinfo.c b/tools/ideviceinfo.c +index 59fade8..a1124cf 100644 +--- a/tools/ideviceinfo.c ++++ b/tools/ideviceinfo.c +@@ -27,6 +27,9 @@ + #include + #include + #include ++#ifndef WIN32 ++#include ++#endif + + #include + #include +@@ -121,6 +124,9 @@ int main(int argc, char *argv[]) + uint32_t xml_length; + plist_t node = NULL; + ++#ifndef WIN32 ++ signal(SIGPIPE, SIG_IGN); ++#endif + /* parse cmdline args */ + for (i = 1; i < argc; i++) { + if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")) { +diff --git a/tools/idevicename.c b/tools/idevicename.c +index ef226f7..a66f5aa 100644 +--- a/tools/idevicename.c ++++ b/tools/idevicename.c +@@ -28,6 +28,9 @@ + #include + #include + #include ++#ifndef WIN32 ++#include ++#endif + + #include + #include +@@ -57,6 +60,10 @@ int main(int argc, char** argv) + { NULL, 0, NULL, 0} + }; + ++#ifndef WIN32 ++ signal(SIGPIPE, SIG_IGN); ++#endif ++ + while ((c = getopt_long(argc, argv, "du:h", longopts, &optidx)) != -1) { + switch (c) { + case 'u': +diff --git a/tools/idevicepair.c b/tools/idevicepair.c +index be1f373..bc0f5d8 100644 +--- a/tools/idevicepair.c ++++ b/tools/idevicepair.c +@@ -28,6 +28,9 @@ + #include + #include + #include ++#ifndef WIN32 ++#include ++#endif + #include "common/userpref.h" + + #include +@@ -134,6 +137,9 @@ int main(int argc, char **argv) + } op_t; + op_t op = OP_NONE; + ++#ifndef WIN32 ++ signal(SIGPIPE, SIG_IGN); ++#endif + parse_opts(argc, argv); + + if ((argc - optind) < 1) { +diff --git a/tools/ideviceprovision.c b/tools/ideviceprovision.c +index 52efdeb..7e8367a 100644 +--- a/tools/ideviceprovision.c ++++ b/tools/ideviceprovision.c +@@ -29,6 +29,9 @@ + #include + #include + #include ++#ifndef WIN32 ++#include ++#endif + + #ifdef WIN32 + #include +@@ -291,6 +294,9 @@ int main(int argc, char *argv[]) + const char* param = NULL; + const char* param2 = NULL; + ++#ifndef WIN32 ++ signal(SIGPIPE, SIG_IGN); ++#endif + /* parse cmdline args */ + for (i = 1; i < argc; i++) { + if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")) { +diff --git a/tools/idevicescreenshot.c b/tools/idevicescreenshot.c +index f2bcd48..38d323c 100644 +--- a/tools/idevicescreenshot.c ++++ b/tools/idevicescreenshot.c +@@ -28,6 +28,9 @@ + #include + #include + #include ++#ifndef WIN32 ++#include ++#endif + + #include + #include +@@ -47,6 +50,9 @@ int main(int argc, char **argv) + const char *udid = NULL; + char *filename = NULL; + ++#ifndef WIN32 ++ signal(SIGPIPE, SIG_IGN); ++#endif + /* parse cmdline args */ + for (i = 1; i < argc; i++) { + if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")) { +-- +2.23.0 + + +From e88fdf99f943c9523ed9f1d30c940804ad99d7de Mon Sep 17 00:00:00 2001 +From: Mikkel Kamstrup Erlandsen +Date: Fri, 27 Sep 2019 10:18:04 +0200 +Subject: [PATCH 136/151] idevice: fix hang in SSL_shutdown + +--- + src/idevice.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/src/idevice.c b/src/idevice.c +index fd1f4b5..90b531d 100644 +--- a/src/idevice.c ++++ b/src/idevice.c +@@ -930,7 +930,13 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_disable_ssl(idevice_conn + if (connection->ssl_data->session) { + /* see: https://www.openssl.org/docs/ssl/SSL_shutdown.html#RETURN_VALUES */ + if (SSL_shutdown(connection->ssl_data->session) == 0) { +- SSL_shutdown(connection->ssl_data->session); ++ /* Only try bidirectional shutdown if we know it can complete */ ++ int ssl_error; ++ if ((ssl_error = SSL_get_error(connection->ssl_data->session, 0)) == SSL_ERROR_NONE) { ++ SSL_shutdown(connection->ssl_data->session); ++ } else { ++ debug_info("Skipping bidirectional SSL shutdown. SSL error code: %i\n", ssl_error); ++ } + } + } + #else +-- +2.23.0 + + +From 656b96ca6caac90eb78266bd1fabe7b76bcb8c03 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Sat, 28 Sep 2019 12:49:17 +0200 +Subject: [PATCH 137/151] cython: Fix all error codes after recent updates + +--- + cython/mobilebackup.pxi | 8 ++++++-- + cython/mobilebackup2.pxi | 10 +++++++--- + cython/mobilesync.pxi | 14 +++++++++----- + cython/restore.pxi | 16 ++++++---------- + cython/screenshotr.pxi | 6 +++++- + 5 files changed, 33 insertions(+), 21 deletions(-) + +diff --git a/cython/mobilebackup.pxi b/cython/mobilebackup.pxi +index 5a6fea6..f2d58d4 100644 +--- a/cython/mobilebackup.pxi ++++ b/cython/mobilebackup.pxi +@@ -8,8 +8,10 @@ cdef extern from "libimobiledevice/mobilebackup.h": + MOBILEBACKUP_E_INVALID_ARG = -1 + MOBILEBACKUP_E_PLIST_ERROR = -2 + MOBILEBACKUP_E_MUX_ERROR = -3 +- MOBILEBACKUP_E_BAD_VERSION = -4 +- MOBILEBACKUP_E_REPLY_NOT_OK = -5 ++ MOBILEBACKUP_E_SSL_ERROR = -4 ++ MOBILEBACKUP_E_RECEIVE_TIMEOUT = -5 ++ MOBILEBACKUP_E_BAD_VERSION = -6 ++ MOBILEBACKUP_E_REPLY_NOT_OK = -7 + MOBILEBACKUP_E_UNKNOWN_ERROR = -256 + + ctypedef enum mobilebackup_flags_t: +@@ -36,6 +38,8 @@ cdef class MobileBackupError(BaseError): + MOBILEBACKUP_E_INVALID_ARG: "Invalid argument", + MOBILEBACKUP_E_PLIST_ERROR: "Property list error", + MOBILEBACKUP_E_MUX_ERROR: "MUX error", ++ MOBILEBACKUP_E_SSL_ERROR: "SSL error", ++ MOBILEBACKUP_E_RECEIVE_TIMEOUT: "Receive timeout", + MOBILEBACKUP_E_BAD_VERSION: "Bad version", + MOBILEBACKUP_E_REPLY_NOT_OK: "Reply not OK", + MOBILEBACKUP_E_UNKNOWN_ERROR: "Unknown error" +diff --git a/cython/mobilebackup2.pxi b/cython/mobilebackup2.pxi +index aac5358..4eccae6 100644 +--- a/cython/mobilebackup2.pxi ++++ b/cython/mobilebackup2.pxi +@@ -8,9 +8,11 @@ cdef extern from "libimobiledevice/mobilebackup2.h": + MOBILEBACKUP2_E_INVALID_ARG = -1 + MOBILEBACKUP2_E_PLIST_ERROR = -2 + MOBILEBACKUP2_E_MUX_ERROR = -3 +- MOBILEBACKUP2_E_BAD_VERSION = -4 +- MOBILEBACKUP2_E_REPLY_NOT_OK = -5 +- MOBILEBACKUP2_E_NO_COMMON_VERSION = -6 ++ MOBILEBACKUP2_E_SSL_ERROR = -4 ++ MOBILEBACKUP2_E_RECEIVE_TIMEOUT = -5 ++ MOBILEBACKUP2_E_BAD_VERSION = -6 ++ MOBILEBACKUP2_E_REPLY_NOT_OK = -7 ++ MOBILEBACKUP2_E_NO_COMMON_VERSION = -8 + MOBILEBACKUP2_E_UNKNOWN_ERROR = -256 + + mobilebackup2_error_t mobilebackup2_client_new(idevice_t device, lockdownd_service_descriptor_t descriptor, mobilebackup2_client_t * client) +@@ -31,6 +33,8 @@ cdef class MobileBackup2Error(BaseError): + MOBILEBACKUP2_E_INVALID_ARG: "Invalid argument", + MOBILEBACKUP2_E_PLIST_ERROR: "Property list error", + MOBILEBACKUP2_E_MUX_ERROR: "MUX error", ++ MOBILEBACKUP2_E_SSL_ERROR: "SSL error", ++ MOBILEBACKUP2_E_RECEIVE_TIMEOUT: "Receive timeout", + MOBILEBACKUP2_E_BAD_VERSION: "Bad version", + MOBILEBACKUP2_E_REPLY_NOT_OK: "Reply not OK", + MOBILEBACKUP2_E_NO_COMMON_VERSION: "No common version", +diff --git a/cython/mobilesync.pxi b/cython/mobilesync.pxi +index ba9d585..8dfe674 100644 +--- a/cython/mobilesync.pxi ++++ b/cython/mobilesync.pxi +@@ -7,11 +7,13 @@ cdef extern from "libimobiledevice/mobilesync.h": + MOBILESYNC_E_INVALID_ARG = -1 + MOBILESYNC_E_PLIST_ERROR = -2 + MOBILESYNC_E_MUX_ERROR = -3 +- MOBILESYNC_E_BAD_VERSION = -4 +- MOBILESYNC_E_SYNC_REFUSED = -5 +- MOBILESYNC_E_CANCELLED = -6 +- MOBILESYNC_E_WRONG_DIRECTION = -7 +- MOBILESYNC_E_NOT_READY = -8 ++ MOBILESYNC_E_SSL_ERROR = -4 ++ MOBILESYNC_E_RECEIVE_TIMEOUT = -5 ++ MOBILESYNC_E_BAD_VERSION = -6 ++ MOBILESYNC_E_SYNC_REFUSED = -7 ++ MOBILESYNC_E_CANCELLED = -8 ++ MOBILESYNC_E_WRONG_DIRECTION = -9 ++ MOBILESYNC_E_NOT_READY = -10 + MOBILESYNC_E_UNKNOWN_ERROR = -256 + + ctypedef enum mobilesync_sync_type_t: +@@ -60,6 +62,8 @@ cdef class MobileSyncError(BaseError): + MOBILESYNC_E_INVALID_ARG: "Invalid argument", + MOBILESYNC_E_PLIST_ERROR: "Property list error", + MOBILESYNC_E_MUX_ERROR: "MUX error", ++ MOBILESYNC_E_SSL_ERROR: "SSL eror", ++ MOBILESYNC_E_RECEIVE_TIMEOUT: "Receive timeout", + MOBILESYNC_E_BAD_VERSION: "Bad version", + MOBILESYNC_E_SYNC_REFUSED: "Sync refused", + MOBILESYNC_E_CANCELLED: "Sync cancelled", +diff --git a/cython/restore.pxi b/cython/restore.pxi +index 7d3d80e..9d03935 100644 +--- a/cython/restore.pxi ++++ b/cython/restore.pxi +@@ -6,12 +6,10 @@ cdef extern from "libimobiledevice/restore.h": + ctypedef enum restored_error_t: + RESTORE_E_SUCCESS = 0 + RESTORE_E_INVALID_ARG = -1 +- RESTORE_E_INVALID_CONF = -2 +- RESTORE_E_PLIST_ERROR = -3 +- RESTORE_E_DICT_ERROR = -4 +- RESTORE_E_NOT_ENOUGH_DATA = -5 +- RESTORE_E_MUX_ERROR = -6 +- RESTORE_E_START_RESTORE_FAILED = -7 ++ RESTORE_E_PLIST_ERROR = -2 ++ RESTORE_E_MUX_ERROR = -3 ++ RESTORE_E_NOT_ENOUGH_DATA = -4 ++ RESTORE_E_RECEIVE_TIMEOUT = -5 + RESTORE_E_UNKNOWN_ERROR = -256 + + restored_error_t restored_client_new(idevice_t device, restored_client_t *client, char *label) +@@ -34,12 +32,10 @@ cdef class RestoreError(BaseError): + self._lookup_table = { + RESTORE_E_SUCCESS: "Success", + RESTORE_E_INVALID_ARG: "Invalid argument", +- RESTORE_E_INVALID_CONF: "Invalid configuration", + RESTORE_E_PLIST_ERROR: "Property list error", +- RESTORE_E_DICT_ERROR: "Dict error", +- RESTORE_E_NOT_ENOUGH_DATA: "Not enough data", + RESTORE_E_MUX_ERROR: "MUX Error", +- RESTORE_E_START_RESTORE_FAILED: "Starting restore failed", ++ RESTORE_E_NOT_ENOUGH_DATA: "Not enough data", ++ RESTORE_E_RECEIVE_TIMEOUT: "Receive timeout", + RESTORE_E_UNKNOWN_ERROR: "Unknown error" + } + BaseError.__init__(self, *args, **kwargs) +diff --git a/cython/screenshotr.pxi b/cython/screenshotr.pxi +index 2b2d53d..a1e82e2 100644 +--- a/cython/screenshotr.pxi ++++ b/cython/screenshotr.pxi +@@ -8,7 +8,9 @@ cdef extern from "libimobiledevice/screenshotr.h": + SCREENSHOTR_E_INVALID_ARG = -1 + SCREENSHOTR_E_PLIST_ERROR = -2 + SCREENSHOTR_E_MUX_ERROR = -3 +- SCREENSHOTR_E_BAD_VERSION = -4 ++ SCREENSHOTR_E_SSL_ERROR = -4 ++ SCREENSHOTR_E_RECEIVE_TIMEOUT = 5 ++ SCREENSHOTR_E_BAD_VERSION = -6 + SCREENSHOTR_E_UNKNOWN_ERROR = -256 + + screenshotr_error_t screenshotr_client_new(idevice_t device, lockdownd_service_descriptor_t descriptor, screenshotr_client_t * client) +@@ -22,6 +24,8 @@ cdef class ScreenshotrError(BaseError): + SCREENSHOTR_E_INVALID_ARG: "Invalid argument", + SCREENSHOTR_E_PLIST_ERROR: "Property list error", + SCREENSHOTR_E_MUX_ERROR: "MUX error", ++ SCREENSHOTR_E_SSL_ERROR: "SSL error", ++ SCREENSHOTR_E_RECEIVE_TIMEOUT: "Receive timeout", + SCREENSHOTR_E_BAD_VERSION: "Bad version", + SCREENSHOTR_E_UNKNOWN_ERROR: "Unknown error" + } +-- +2.23.0 + + +From 60823f9eeb3f09cd8083f613522d01e21d2f6d2d Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Sun, 29 Sep 2019 17:10:46 +0200 +Subject: [PATCH 138/151] idevice: properly handle partial SSL writes + +--- + src/idevice.c | 23 +++++++++++++++-------- + 1 file changed, 15 insertions(+), 8 deletions(-) + +diff --git a/src/idevice.c b/src/idevice.c +index 90b531d..06991c5 100644 +--- a/src/idevice.c ++++ b/src/idevice.c +@@ -384,18 +384,25 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_send(idevice_connection_ + } + + if (connection->ssl_data) { ++ uint32_t sent = 0; ++ while (sent < len) { + #ifdef HAVE_OPENSSL +- int sent = SSL_write(connection->ssl_data->session, (const void*)data, (int)len); +- debug_info("SSL_write %d, sent %d", len, sent); ++ int s = SSL_write(connection->ssl_data->session, (const void*)(data+sent), (int)(len-sent)); + #else +- ssize_t sent = gnutls_record_send(connection->ssl_data->session, (void*)data, (size_t)len); ++ ssize_t s = gnutls_record_send(connection->ssl_data->session, (void*)(data+sent), (size_t)(len-sent)); + #endif +- if ((uint32_t)sent == (uint32_t)len) { +- *sent_bytes = sent; +- return IDEVICE_E_SUCCESS; ++ if (s < 0) { ++ break; ++ } ++ sent += s; + } +- *sent_bytes = 0; +- return IDEVICE_E_SSL_ERROR; ++ debug_info("SSL_write %d, sent %d", len, sent); ++ if (sent < len) { ++ *sent_bytes = 0; ++ return IDEVICE_E_SSL_ERROR; ++ } ++ *sent_bytes = sent; ++ return IDEVICE_E_SUCCESS; + } + return internal_connection_send(connection, data, len, sent_bytes); + } +-- +2.23.0 + + +From d323e9ccdf3919de51513d291982d3c002528f0f Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Mon, 30 Sep 2019 00:52:57 +0200 +Subject: [PATCH 139/151] idevicebackup2: Only print device reboot message if + restore was successful + +--- + tools/idevicebackup2.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/tools/idevicebackup2.c b/tools/idevicebackup2.c +index 3a4de67..10fad81 100644 +--- a/tools/idevicebackup2.c ++++ b/tools/idevicebackup2.c +@@ -1409,7 +1409,7 @@ static void print_usage(int argc, char **argv) + printf(" --full\t\tforce full backup from device.\n"); + printf(" restore\trestore last backup to the device\n"); + printf(" --system\t\trestore system files, too.\n"); +- printf(" --no-reboot\t\tdo NOT reboot the system when done (default: yes).\n"); ++ printf(" --no-reboot\t\tdo NOT reboot the device when done (default: yes).\n"); + printf(" --copy\t\tcreate a copy of backup folder before restoring.\n"); + printf(" --settings\t\trestore device settings from the backup.\n"); + printf(" --remove\t\tremove items which are not being restored\n"); +@@ -2499,9 +2499,9 @@ files_out: + } + break; + case CMD_RESTORE: +- if ((cmd_flags & CMD_FLAG_RESTORE_NO_REBOOT) == 0) +- PRINT_VERBOSE(1, "The device should reboot now.\n"); + if (operation_ok) { ++ if ((cmd_flags & CMD_FLAG_RESTORE_NO_REBOOT) == 0) ++ PRINT_VERBOSE(1, "The device should reboot now.\n"); + PRINT_VERBOSE(1, "Restore Successful.\n"); + } else { + PRINT_VERBOSE(1, "Restore Failed (Error Code %d).\n", -result_code); +-- +2.23.0 + + +From 4f8ed2eba843dbf3a17243d75414a96a9b330942 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Mon, 30 Sep 2019 00:53:30 +0200 +Subject: [PATCH 140/151] idevicebackup2: Remove RestoreApplications.plist if + restore failed + +--- + tools/idevicebackup2.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/tools/idevicebackup2.c b/tools/idevicebackup2.c +index 10fad81..c2f04c2 100644 +--- a/tools/idevicebackup2.c ++++ b/tools/idevicebackup2.c +@@ -2504,7 +2504,13 @@ files_out: + PRINT_VERBOSE(1, "The device should reboot now.\n"); + PRINT_VERBOSE(1, "Restore Successful.\n"); + } else { +- PRINT_VERBOSE(1, "Restore Failed (Error Code %d).\n", -result_code); ++ afc_remove_path(afc, "/iTunesRestore/RestoreApplications.plist"); ++ afc_remove_path(afc, "/iTunesRestore"); ++ if (quit_flag) { ++ PRINT_VERBOSE(1, "Restore Aborted.\n"); ++ } else { ++ PRINT_VERBOSE(1, "Restore Failed (Error Code %d).\n", -result_code); ++ } + } + break; + case CMD_INFO: +-- +2.23.0 + + +From 8872aec759699411be45a17798dab40b9539c2ae Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Tue, 29 Oct 2019 09:56:17 +0100 +Subject: [PATCH 141/151] property_list_service: Consider a successful 0 byte + read a timeout rather than an error condition + +--- + src/property_list_service.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/src/property_list_service.c b/src/property_list_service.c +index 1cb8dc9..9d47fd6 100644 +--- a/src/property_list_service.c ++++ b/src/property_list_service.c +@@ -197,6 +197,11 @@ static property_list_service_error_t internal_plist_receive_timeout(property_lis + return service_to_property_list_service_error(serr); + } + ++ if (bytes == 0) { ++ /* success but 0 bytes length, assume timeout */ ++ return PROPERTY_LIST_SERVICE_E_RECEIVE_TIMEOUT; ++ } ++ + debug_info("initial read=%i", bytes); + + uint32_t curlen = 0; +-- +2.23.0 + + +From 5390060ec90bed0f565698a389cebc57c09c3ac8 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Thu, 7 Nov 2019 23:25:55 +0100 +Subject: [PATCH 142/151] Add propert support for network (WiFi) devices via + new idevice_new_with_options() + +--- + include/libimobiledevice/libimobiledevice.h | 56 +++++++++++-- + src/idevice.c | 92 ++++++++++++++++----- + src/idevice.h | 8 +- + 3 files changed, 124 insertions(+), 32 deletions(-) + +diff --git a/include/libimobiledevice/libimobiledevice.h b/include/libimobiledevice/libimobiledevice.h +index 8f8589d..c1d5460 100644 +--- a/include/libimobiledevice/libimobiledevice.h ++++ b/include/libimobiledevice/libimobiledevice.h +@@ -3,6 +3,7 @@ + * @brief Device/Connection handling and communication + * \internal + * ++ * Copyright (c) 2010-2019 Nikias Bassen All Rights Reserved. + * Copyright (c) 2010-2014 Martin Szulecki All Rights Reserved. + * Copyright (c) 2014 Christophe Fergeau All Rights Reserved. + * Copyright (c) 2008 Jonathan Beck All Rights Reserved. +@@ -51,6 +52,26 @@ typedef idevice_private *idevice_t; /**< The device handle. */ + typedef struct idevice_connection_private idevice_connection_private; + typedef idevice_connection_private *idevice_connection_t; /**< The connection handle. */ + ++/** Options for idevice_new_with_options() */ ++enum idevice_options { ++ IDEVICE_LOOKUP_USBMUX = 1 << 1, /**< include USBMUX devices during lookup */ ++ IDEVICE_LOOKUP_NETWORK = 1 << 2, /**< include network devices during lookup */ ++ IDEVICE_LOOKUP_PREFER_NETWORK = 1 << 3 /**< prefer network connection if device is available via USBMUX *and* network */ ++}; ++ ++/** Type of connection a device is available on */ ++enum idevice_connection_type { ++ CONNECTION_USBMUXD = 1, ++ CONNECTION_NETWORK ++}; ++ ++struct idevice_info { ++ char *udid; ++ enum idevice_connection_type conn_type; ++ void* conn_data; ++}; ++typedef struct idevice_info* idevice_info_t; ++ + /* discovery (events/asynchronous) */ + /** The event type for device add or removal */ + enum idevice_event_type { +@@ -64,7 +85,7 @@ enum idevice_event_type { + typedef struct { + enum idevice_event_type event; /**< The event type. */ + const char *udid; /**< The device unique id. */ +- int conn_type; /**< The connection type. Currently only 1 for usbmuxd. */ ++ enum idevice_connection_type conn_type; /**< The connection type. */ + } idevice_event_t; + + /* event callback function prototype */ +@@ -125,11 +146,15 @@ idevice_error_t idevice_device_list_free(char **devices); + /* device structure creation and destruction */ + + /** +- * Creates an idevice_t structure for the device specified by udid, +- * if the device is available. ++ * Creates an idevice_t structure for the device specified by UDID, ++ * if the device is available (USBMUX devices only). + * + * @note The resulting idevice_t structure has to be freed with + * idevice_free() if it is no longer used. ++ * If you need to connect to a device available via network, use ++ * idevice_new_with_options() and include IDEVICE_LOOKUP_NETWORK in options. ++ * ++ * @see idevice_new_with_options + * + * @param device Upon calling this function, a pointer to a location of type + * idevice_t. On successful return, this location will be populated. +@@ -139,10 +164,31 @@ idevice_error_t idevice_device_list_free(char **devices); + */ + idevice_error_t idevice_new(idevice_t *device, const char *udid); + ++/** ++ * Creates an idevice_t structure for the device specified by UDID, ++ * if the device is available, with the given lookup options. ++ * ++ * @note The resulting idevice_t structure has to be freed with ++ * idevice_free() if it is no longer used. ++ * ++ * @param device Upon calling this function, a pointer to a location of type ++ * idevice_t. On successful return, this location will be populated. ++ * @param udid The UDID to match. ++ * @param options Specifies what connection types should be considered ++ * when looking up devices. Accepts bitwise or'ed values of idevice_options. ++ * If 0 (no option) is specified it will default to IDEVICE_LOOKUP_USBMUX. ++ * To lookup both USB and network-connected devices, pass ++ * IDEVICE_LOOKUP_USBMUX | IDEVICE_LOOKUP_NETWORK. If a device is available ++ * both via USBMUX *and* network, it will select the USB connection. ++ * This behavior can be changed by adding IDEVICE_LOOKUP_PREFER_NETWORK ++ * to the options in which case it will select the network connection. ++ * ++ * @return IDEVICE_E_SUCCESS if ok, otherwise an error code. ++ */ ++idevice_error_t idevice_new_with_options(idevice_t *device, const char *udid, enum idevice_options options); ++ + /** + * Cleans up an idevice structure, then frees the structure itself. +- * This is a library-level function; deals directly with the device to tear +- * down relations, but otherwise is mostly internal. + * + * @param device idevice_t to free. + */ +diff --git a/src/idevice.c b/src/idevice.c +index 06991c5..d23c5b5 100644 +--- a/src/idevice.c ++++ b/src/idevice.c +@@ -190,7 +190,14 @@ static void usbmux_event_cb(const usbmuxd_event_t *event, void *user_data) + + ev.event = event->event; + ev.udid = event->device.udid; +- ev.conn_type = CONNECTION_USBMUXD; ++ ev.conn_type = 0; ++ if (event->device.conn_type == CONNECTION_TYPE_USB) { ++ ev.conn_type = CONNECTION_USBMUXD; ++ } else if (event->device.conn_type == CONNECTION_TYPE_NETWORK) { ++ ev.conn_type = CONNECTION_NETWORK; ++ } else { ++ debug_info("Unknown connection type %d", event->device.conn_type); ++ } + + if (event_cb) { + event_cb(&ev, user_data); +@@ -236,9 +243,11 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_get_device_list(char ***devices, in + int i, newcount = 0; + + for (i = 0; dev_list[i].handle > 0; i++) { +- newlist = realloc(*devices, sizeof(char*) * (newcount+1)); +- newlist[newcount++] = strdup(dev_list[i].udid); +- *devices = newlist; ++ if (dev_list[i].conn_type == CONNECTION_TYPE_USB) { ++ newlist = realloc(*devices, sizeof(char*) * (newcount+1)); ++ newlist[newcount++] = strdup(dev_list[i].udid); ++ *devices = newlist; ++ } + } + usbmuxd_device_list_free(&dev_list); + +@@ -268,25 +277,66 @@ LIBIMOBILEDEVICE_API void idevice_set_debug_level(int level) + internal_set_debug_level(level); + } + +-LIBIMOBILEDEVICE_API idevice_error_t idevice_new(idevice_t * device, const char *udid) ++static idevice_t idevice_from_mux_device(usbmuxd_device_info_t *muxdev) ++{ ++ if (!muxdev) ++ return NULL; ++ ++ idevice_t device = (idevice_t)malloc(sizeof(struct idevice_private)); ++ if (!device) ++ return NULL; ++ ++ device->udid = strdup(muxdev->udid); ++ device->mux_id = muxdev->handle; ++ device->version = 0; ++ switch (muxdev->conn_type) { ++ case CONNECTION_TYPE_USB: ++ device->conn_type = CONNECTION_USBMUXD; ++ device->conn_data = NULL; ++ break; ++ case CONNECTION_TYPE_NETWORK: ++ device->conn_type = CONNECTION_NETWORK; ++ size_t len = ((uint8_t*)muxdev->conn_data)[0]; ++ device->conn_data = malloc(len); ++ memcpy(device->conn_data, muxdev->conn_data, len); ++ break; ++ default: ++ device->conn_type = 0; ++ device->conn_data = NULL; ++ break; ++ } ++ return device; ++} ++ ++LIBIMOBILEDEVICE_API idevice_error_t idevice_new_with_options(idevice_t * device, const char *udid, enum idevice_options options) + { + usbmuxd_device_info_t muxdev; +- int res = usbmuxd_get_device_by_udid(udid, &muxdev); ++ int usbmux_options = 0; ++ if (options & IDEVICE_LOOKUP_USBMUX) { ++ usbmux_options |= DEVICE_LOOKUP_USBMUX; ++ } ++ if (options & IDEVICE_LOOKUP_NETWORK) { ++ usbmux_options |= DEVICE_LOOKUP_NETWORK; ++ } ++ if (options & IDEVICE_LOOKUP_PREFER_NETWORK) { ++ usbmux_options |= DEVICE_LOOKUP_PREFER_NETWORK; ++ } ++ int res = usbmuxd_get_device(udid, &muxdev, usbmux_options); + if (res > 0) { +- idevice_t dev = (idevice_t) malloc(sizeof(struct idevice_private)); +- dev->udid = strdup(muxdev.udid); +- dev->mux_id = muxdev.handle; +- dev->conn_type = CONNECTION_USBMUXD; +- dev->conn_data = NULL; +- dev->version = 0; +- *device = dev; ++ *device = idevice_from_mux_device(&muxdev); ++ if (!*device) { ++ return IDEVICE_E_UNKNOWN_ERROR; ++ } + return IDEVICE_E_SUCCESS; + } +- /* other connection types could follow here */ +- + return IDEVICE_E_NO_DEVICE; + } + ++LIBIMOBILEDEVICE_API idevice_error_t idevice_new(idevice_t * device, const char *udid) ++{ ++ return idevice_new_with_options(device, udid, 0); ++} ++ + LIBIMOBILEDEVICE_API idevice_error_t idevice_free(idevice_t device) + { + if (!device) +@@ -310,7 +360,7 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connect(idevice_t device, uint16_t + return IDEVICE_E_INVALID_ARG; + } + +- if (device->conn_type == CONNECTION_USBMUXD) { ++ if (device->conn_type == CONNECTION_USBMUXD || device->conn_type == CONNECTION_NETWORK) { + int sfd = usbmuxd_connect(device->mux_id, port); + if (sfd < 0) { + debug_info("ERROR: Connecting to usbmuxd failed: %d (%s)", sfd, strerror(-sfd)); +@@ -340,7 +390,7 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_disconnect(idevice_connection_t con + idevice_connection_disable_ssl(connection); + } + idevice_error_t result = IDEVICE_E_UNKNOWN_ERROR; +- if (connection->type == CONNECTION_USBMUXD) { ++ if (connection->type == CONNECTION_USBMUXD || connection->type == CONNECTION_NETWORK) { + usbmuxd_disconnect((int)(long)connection->data); + connection->data = NULL; + result = IDEVICE_E_SUCCESS; +@@ -363,7 +413,7 @@ static idevice_error_t internal_connection_send(idevice_connection_t connection, + return IDEVICE_E_INVALID_ARG; + } + +- if (connection->type == CONNECTION_USBMUXD) { ++ if (connection->type == CONNECTION_USBMUXD || connection->type == CONNECTION_NETWORK) { + int res = usbmuxd_send((int)(long)connection->data, data, len, sent_bytes); + if (res < 0) { + debug_info("ERROR: usbmuxd_send returned %d (%s)", res, strerror(-res)); +@@ -434,7 +484,7 @@ static idevice_error_t internal_connection_receive_timeout(idevice_connection_t + return IDEVICE_E_INVALID_ARG; + } + +- if (connection->type == CONNECTION_USBMUXD) { ++ if (connection->type == CONNECTION_USBMUXD || connection->type == CONNECTION_NETWORK) { + int conn_error = usbmuxd_recv_timeout((int)(long)connection->data, data, len, recv_bytes, timeout); + idevice_error_t error = socket_recv_to_idevice_error(conn_error, len, *recv_bytes); + +@@ -510,7 +560,7 @@ static idevice_error_t internal_connection_receive(idevice_connection_t connecti + return IDEVICE_E_INVALID_ARG; + } + +- if (connection->type == CONNECTION_USBMUXD) { ++ if (connection->type == CONNECTION_USBMUXD || connection->type == CONNECTION_NETWORK) { + int res = usbmuxd_recv((int)(long)connection->data, data, len, recv_bytes); + if (res < 0) { + debug_info("ERROR: usbmuxd_recv returned %d (%s)", res, strerror(-res)); +@@ -554,7 +604,7 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_get_fd(idevice_connectio + } + + idevice_error_t result = IDEVICE_E_UNKNOWN_ERROR; +- if (connection->type == CONNECTION_USBMUXD) { ++ if (connection->type == CONNECTION_USBMUXD || connection->type == CONNECTION_NETWORK) { + *fd = (int)(long)connection->data; + result = IDEVICE_E_SUCCESS; + } else { +diff --git a/src/idevice.h b/src/idevice.h +index f403c55..8709c9a 100644 +--- a/src/idevice.h ++++ b/src/idevice.h +@@ -48,10 +48,6 @@ + + #define DEVICE_VERSION(maj, min, patch) (((maj & 0xFF) << 16) | ((min & 0xFF) << 8) | (patch & 0xFF)) + +-enum connection_type { +- CONNECTION_USBMUXD = 1 +-}; +- + struct ssl_data_private { + #ifdef HAVE_OPENSSL + SSL *session; +@@ -69,7 +65,7 @@ typedef struct ssl_data_private *ssl_data_t; + + struct idevice_connection_private { + idevice_t device; +- enum connection_type type; ++ enum idevice_connection_type type; + void *data; + ssl_data_t ssl_data; + }; +@@ -77,7 +73,7 @@ struct idevice_connection_private { + struct idevice_private { + char *udid; + uint32_t mux_id; +- enum connection_type conn_type; ++ enum idevice_connection_type conn_type; + void *conn_data; + int version; + }; +-- +2.23.0 + + +From 953c13961071a9836430a814159aae33502e2e0c Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Thu, 7 Nov 2019 23:29:00 +0100 +Subject: [PATCH 143/151] Add new idevice_get_device_list_extended() allowing + to list all devices, including network + +Instead of just returning a list of UDIDs (like idevice_get_device_list) this +function will return idevice_info_t* records which also contains the type of +the connection and the connection data. +--- + include/libimobiledevice/libimobiledevice.h | 32 ++++++++++-- + src/idevice.c | 56 +++++++++++++++++++++ + 2 files changed, 84 insertions(+), 4 deletions(-) + +diff --git a/include/libimobiledevice/libimobiledevice.h b/include/libimobiledevice/libimobiledevice.h +index c1d5460..8bf022a 100644 +--- a/include/libimobiledevice/libimobiledevice.h ++++ b/include/libimobiledevice/libimobiledevice.h +@@ -124,25 +124,49 @@ idevice_error_t idevice_event_unsubscribe(void); + /* discovery (synchronous) */ + + /** +- * Get a list of currently available devices. ++ * Get a list of UDIDs of currently available devices (USBMUX devices only). + * +- * @param devices List of udids of devices that are currently available. ++ * @param devices List of UDIDs of devices that are currently available. + * This list is terminated by a NULL pointer. + * @param count Number of devices found. + * + * @return IDEVICE_E_SUCCESS on success or an error value when an error occurred. ++ * ++ * @note This function only returns the UDIDs of USBMUX devices. To also include ++ * network devices in the list, use idevice_get_device_list_extended(). ++ * @see idevice_get_device_list_extended + */ + idevice_error_t idevice_get_device_list(char ***devices, int *count); + + /** +- * Free a list of device udids. ++ * Free a list of device UDIDs. + * +- * @param devices List of udids to free. ++ * @param devices List of UDIDs to free. + * + * @return Always returnes IDEVICE_E_SUCCESS. + */ + idevice_error_t idevice_device_list_free(char **devices); + ++/** ++ * Get a list of currently available devices ++ * ++ * @param devices List of idevice_info_t records with device information. ++ * This list is terminated by a NULL pointer. ++ * @param count Number of devices included in the list. ++ * ++ * @return IDEVICE_E_SUCCESS on success or an error value when an error occurred. ++ */ ++idevice_error_t idevice_get_device_list_extended(idevice_info_t **devices, int *count); ++ ++/** ++ * Free an extended device list retrieved through idevice_get_device_list_extended(). ++ * ++ * @param devices Device list to free. ++ * ++ * @return IDEVICE_E_SUCCESS on success or an error value when an error occurred. ++ */ ++idevice_error_t idevice_device_list_extended_free(idevice_info_t *devices); ++ + /* device structure creation and destruction */ + + /** +diff --git a/src/idevice.c b/src/idevice.c +index d23c5b5..31a8d3a 100644 +--- a/src/idevice.c ++++ b/src/idevice.c +@@ -227,6 +227,62 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_event_unsubscribe(void) + return IDEVICE_E_SUCCESS; + } + ++LIBIMOBILEDEVICE_API idevice_error_t idevice_get_device_list_extended(idevice_info_t **devices, int *count) ++{ ++ usbmuxd_device_info_t *dev_list; ++ ++ *devices = NULL; ++ *count = 0; ++ ++ if (usbmuxd_get_device_list(&dev_list) < 0) { ++ debug_info("ERROR: usbmuxd is not running!", __func__); ++ return IDEVICE_E_NO_DEVICE; ++ } ++ ++ idevice_info_t *newlist = NULL; ++ int i, newcount = 0; ++ ++ for (i = 0; dev_list[i].handle > 0; i++) { ++ newlist = realloc(*devices, sizeof(idevice_info_t) * (newcount+1)); ++ newlist[newcount] = malloc(sizeof(struct idevice_info)); ++ newlist[newcount]->udid = strdup(dev_list[i].udid); ++ if (dev_list[i].conn_type == CONNECTION_TYPE_USB) { ++ newlist[newcount]->conn_type = CONNECTION_USBMUXD; ++ newlist[newcount]->conn_data = NULL; ++ } else if (dev_list[i].conn_type == CONNECTION_TYPE_NETWORK) { ++ newlist[newcount]->conn_type = CONNECTION_NETWORK; ++ size_t addrlen = dev_list[i].conn_data[0]; ++ newlist[newcount]->conn_data = malloc(addrlen); ++ memcpy(newlist[newcount]->conn_data, dev_list[i].conn_data, addrlen); ++ } ++ newcount++; ++ *devices = newlist; ++ } ++ usbmuxd_device_list_free(&dev_list); ++ ++ *count = newcount; ++ newlist = realloc(*devices, sizeof(idevice_info_t) * (newcount+1)); ++ newlist[newcount] = NULL; ++ *devices = newlist; ++ ++ return IDEVICE_E_SUCCESS; ++} ++ ++LIBIMOBILEDEVICE_API idevice_error_t idevice_device_list_extended_free(idevice_info_t *devices) ++{ ++ if (devices) { ++ int i = 0; ++ while (devices[i]) { ++ free(devices[i]->udid); ++ free(devices[i]->conn_data); ++ free(devices[i]); ++ i++; ++ } ++ free(devices); ++ } ++ return IDEVICE_E_SUCCESS; ++} ++ + LIBIMOBILEDEVICE_API idevice_error_t idevice_get_device_list(char ***devices, int *count) + { + usbmuxd_device_info_t *dev_list; +-- +2.23.0 + + +From 74dfc6485b61c76775c332f0ae6c65a28bcced9c Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Thu, 7 Nov 2019 23:34:37 +0100 +Subject: [PATCH 144/151] tools: Update idevice_id with new API to allow + listing available network devices + +Using the -n option, idevice_id will print available network devices while +-l will only print available USB devices. +--- + tools/idevice_id.c | 118 ++++++++++++++++++++++++++++----------------- + 1 file changed, 75 insertions(+), 43 deletions(-) + +diff --git a/tools/idevice_id.c b/tools/idevice_id.c +index 8d888c0..963d1d5 100644 +--- a/tools/idevice_id.c ++++ b/tools/idevice_id.c +@@ -2,7 +2,7 @@ + * idevice_id.c + * Prints device name or a list of attached devices + * +- * Copyright (C) 2010 Nikias Bassen ++ * Copyright (C) 2010-2018 Nikias Bassen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public +@@ -26,10 +26,7 @@ + #include + #include + #include +-#ifndef WIN32 +-#include +-#endif +- ++#include + #include + #include + +@@ -37,65 +34,90 @@ + #define MODE_SHOW_ID 1 + #define MODE_LIST_DEVICES 2 + +-static void print_usage(int argc, char **argv) ++static void print_usage(int argc, char **argv, int is_error) + { + char *name = NULL; +- + name = strrchr(argv[0], '/'); +- printf("Usage: %s [OPTIONS] [UDID]\n", (name ? name + 1: argv[0])); +- printf("Prints device name or a list of attached devices.\n\n"); +- printf(" UDID is the unique device identifier of the device\n"); +- printf(" for which the name should be retrieved.\n\n"); +- printf(" -l, --list\t\tlist UDID of all attached devices\n"); +- printf(" -d, --debug\t\tenable communication debugging\n"); +- printf(" -h, --help\t\tprints usage information\n"); +- printf("\n"); +- printf("Homepage: <" PACKAGE_URL ">\n"); ++ fprintf(is_error ? stderr : stdout, "Usage: %s [OPTIONS] [UDID]\n", (name ? name + 1: argv[0])); ++ fprintf(is_error ? stderr : stdout, ++ "Prints device name or a list of attached devices.\n\n" \ ++ " If UDID is given, the name of the connected device with that UDID" \ ++ " will be retrieved.\n\n" \ ++ " -l, --list list UDIDs of all devices attached via USB\n" \ ++ " -n, --network list UDIDs of all devices available via network\n" \ ++ " -d, --debug enable communication debugging\n" \ ++ " -h, --help prints usage information\n" \ ++ "\n" \ ++ "Homepage: <" PACKAGE_URL ">\n" ++ ); + } + + int main(int argc, char **argv) + { + idevice_t device = NULL; + lockdownd_client_t client = NULL; +- char **dev_list = NULL; ++ idevice_info_t *dev_list = NULL; + char *device_name = NULL; + int ret = 0; + int i; + int mode = MODE_SHOW_ID; ++ int include_usb = 0; ++ int include_network = 0; + const char* udid = NULL; + +-#ifndef WIN32 +- signal(SIGPIPE, SIG_IGN); +-#endif +- /* parse cmdline args */ +- for (i = 1; i < argc; i++) { +- if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")) { ++ int c = 0; ++ const struct option longopts[] = { ++ { "debug", no_argument, NULL, 'd' }, ++ { "help", no_argument, NULL, 'h' }, ++ { "list", no_argument, NULL, 'l' }, ++ { "network", no_argument, NULL, 'n' }, ++ { NULL, 0, NULL, 0} ++ }; ++ ++ while ((c = getopt_long(argc, argv, "dhln", longopts, NULL)) != -1) { ++ switch (c) { ++ case 'd': + idevice_set_debug_level(1); +- continue; +- } +- else if (!strcmp(argv[i], "-l") || !strcmp(argv[i], "--list")) { ++ break; ++ case 'h': ++ print_usage(argc, argv, 0); ++ exit(EXIT_SUCCESS); ++ case 'l': + mode = MODE_LIST_DEVICES; +- continue; +- } +- else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { +- print_usage(argc, argv); +- return 0; ++ include_usb = 1; ++ break; ++ case 'n': ++ mode = MODE_LIST_DEVICES; ++ include_network = 1; ++ break; ++ default: ++ print_usage(argc, argv, 1); ++ exit(EXIT_FAILURE); + } + } ++ argc -= optind; ++ argv += optind; + +- /* check if udid was passed */ +- if (mode == MODE_SHOW_ID) { +- i--; +- if (argc < 2 || !argv[i] || !*argv[i]) { +- print_usage(argc, argv); +- return 0; +- } +- udid = argv[i]; ++ if (mode == MODE_SHOW_ID && argc != 1) { ++ print_usage(argc + optind, argv - optind, 1); ++ exit(EXIT_FAILURE); ++ } ++ udid = argv[0]; ++ ++ enum idevice_connection_type conn_type = 0; ++ enum idevice_options opts = 0; ++ if (include_usb) { ++ conn_type |= CONNECTION_USBMUXD; ++ opts |= IDEVICE_LOOKUP_USBMUX; ++ } ++ if (include_network) { ++ conn_type |= CONNECTION_NETWORK; ++ opts |= IDEVICE_LOOKUP_NETWORK; + } + + switch (mode) { + case MODE_SHOW_ID: +- idevice_new(&device, udid); ++ idevice_new_with_options(&device, udid, opts); + if (!device) { + fprintf(stderr, "ERROR: No device with UDID %s attached.\n", udid); + return -2; +@@ -126,14 +148,24 @@ int main(int argc, char **argv) + return ret; + case MODE_LIST_DEVICES: + default: +- if (idevice_get_device_list(&dev_list, &i) < 0) { ++ if (idevice_get_device_list_extended(&dev_list, &i) < 0) { + fprintf(stderr, "ERROR: Unable to retrieve device list!\n"); + return -1; + } + for (i = 0; dev_list[i] != NULL; i++) { +- printf("%s\n", dev_list[i]); ++ if (dev_list[i]->conn_type & conn_type) { ++ printf("%s", dev_list[i]->udid); ++ if (include_usb && include_network) { ++ if (dev_list[i]->conn_type == CONNECTION_NETWORK) { ++ printf(" (WiFi)"); ++ } else { ++ printf(" (USB)"); ++ } ++ } ++ printf("\n"); ++ } + } +- idevice_device_list_free(dev_list); ++ idevice_device_list_extended_free(dev_list); + return 0; + } + } +-- +2.23.0 + + +From 6a73100414f66d12287105a322529c488f32182e Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Fri, 8 Nov 2019 00:34:47 +0100 +Subject: [PATCH 145/151] tools: Small fixes for idevice_id + +--- + tools/idevice_id.c | 36 +++++++++++++----------------------- + 1 file changed, 13 insertions(+), 23 deletions(-) + +diff --git a/tools/idevice_id.c b/tools/idevice_id.c +index 963d1d5..b746491 100644 +--- a/tools/idevice_id.c ++++ b/tools/idevice_id.c +@@ -104,20 +104,9 @@ int main(int argc, char **argv) + } + udid = argv[0]; + +- enum idevice_connection_type conn_type = 0; +- enum idevice_options opts = 0; +- if (include_usb) { +- conn_type |= CONNECTION_USBMUXD; +- opts |= IDEVICE_LOOKUP_USBMUX; +- } +- if (include_network) { +- conn_type |= CONNECTION_NETWORK; +- opts |= IDEVICE_LOOKUP_NETWORK; +- } +- + switch (mode) { + case MODE_SHOW_ID: +- idevice_new_with_options(&device, udid, opts); ++ idevice_new_with_options(&device, udid, IDEVICE_LOOKUP_USBMUX | IDEVICE_LOOKUP_NETWORK); + if (!device) { + fprintf(stderr, "ERROR: No device with UDID %s attached.\n", udid); + return -2; +@@ -144,8 +133,8 @@ int main(int argc, char **argv) + if (device_name) { + free(device_name); + } ++ break; + +- return ret; + case MODE_LIST_DEVICES: + default: + if (idevice_get_device_list_extended(&dev_list, &i) < 0) { +@@ -153,19 +142,20 @@ int main(int argc, char **argv) + return -1; + } + for (i = 0; dev_list[i] != NULL; i++) { +- if (dev_list[i]->conn_type & conn_type) { +- printf("%s", dev_list[i]->udid); +- if (include_usb && include_network) { +- if (dev_list[i]->conn_type == CONNECTION_NETWORK) { +- printf(" (WiFi)"); +- } else { +- printf(" (USB)"); +- } ++ if (dev_list[i]->conn_type == CONNECTION_USBMUXD && !include_usb) continue; ++ if (dev_list[i]->conn_type == CONNECTION_NETWORK && !include_network) continue; ++ printf("%s", dev_list[i]->udid); ++ if (include_usb && include_network) { ++ if (dev_list[i]->conn_type == CONNECTION_NETWORK) { ++ printf(" (WiFi)"); ++ } else { ++ printf(" (USB)"); + } +- printf("\n"); + } ++ printf("\n"); + } + idevice_device_list_extended_free(dev_list); +- return 0; ++ break; + } ++ return ret; + } +-- +2.23.0 + + +From fe3ef93359d9a1105b920d4a7a342706bd3b32c0 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Fri, 8 Nov 2019 00:53:51 +0100 +Subject: [PATCH 146/151] Add new function lockdown_strerror() to get a + readable description of a lockdownd_error_t + +--- + include/libimobiledevice/lockdown.h | 9 ++ + src/lockdown.c | 146 ++++++++++++++++------------ + 2 files changed, 93 insertions(+), 62 deletions(-) + +diff --git a/include/libimobiledevice/lockdown.h b/include/libimobiledevice/lockdown.h +index b5c126c..d0ab037 100644 +--- a/include/libimobiledevice/lockdown.h ++++ b/include/libimobiledevice/lockdown.h +@@ -464,6 +464,15 @@ lockdownd_error_t lockdownd_data_classes_free(char **classes); + */ + lockdownd_error_t lockdownd_service_descriptor_free(lockdownd_service_descriptor_t service); + ++/** ++ * Gets a readable error string for a given lockdown error code. ++ * ++ * @params err A lockdownd error code ++ * ++ * @returns A readable error string ++ */ ++const char* lockdownd_strerror(lockdownd_error_t err); ++ + #ifdef __cplusplus + } + #endif +diff --git a/src/lockdown.c b/src/lockdown.c +index 694fb47..0f6b93d 100644 +--- a/src/lockdown.c ++++ b/src/lockdown.c +@@ -57,6 +57,46 @@ + #define sleep(x) Sleep(x*1000) + #endif + ++struct st_lockdownd_error_str_map { ++ const char *lockdown_errstr; ++ const char *errstr; ++ lockdownd_error_t errcode; ++}; ++ ++static struct st_lockdownd_error_str_map lockdownd_error_str_map[] = { ++ { "InvalidResponse", "Invalid response", LOCKDOWN_E_INVALID_RESPONSE }, ++ { "MissingKey", "Missing key", LOCKDOWN_E_MISSING_KEY }, ++ { "MissingValue", "Missing value", LOCKDOWN_E_MISSING_VALUE }, ++ { "GetProhibited", "Get value prohibited", LOCKDOWN_E_GET_PROHIBITED }, ++ { "SetProhibited", "Set value prohibited", LOCKDOWN_E_SET_PROHIBITED }, ++ { "RemoveProhibited", "Remove value prohibited", LOCKDOWN_E_REMOVE_PROHIBITED }, ++ { "ImmutableValue", "Immutable value", LOCKDOWN_E_IMMUTABLE_VALUE }, ++ { "PasswordProtected", "Password protected", LOCKDOWN_E_PASSWORD_PROTECTED }, ++ { "UserDeniedPairing", "User denied pairing", LOCKDOWN_E_USER_DENIED_PAIRING }, ++ { "PairingDialogResponsePending", "Pairing dialog response pending", LOCKDOWN_E_PAIRING_DIALOG_RESPONSE_PENDING }, ++ { "MissingHostID", "Missing HostID", LOCKDOWN_E_MISSING_HOST_ID }, ++ { "InvalidHostID", "Invalid HostID", LOCKDOWN_E_INVALID_HOST_ID }, ++ { "SessionActive", "Session active", LOCKDOWN_E_SESSION_ACTIVE }, ++ { "SessionInactive", "Session inactive", LOCKDOWN_E_SESSION_INACTIVE }, ++ { "MissingSessionID", "Missing session ID", LOCKDOWN_E_MISSING_SESSION_ID }, ++ { "InvalidSessionID", "Invalid session ID", LOCKDOWN_E_INVALID_SESSION_ID }, ++ { "MissingService", "Missing service", LOCKDOWN_E_MISSING_SERVICE }, ++ { "InvalidService", "Invalid service", LOCKDOWN_E_INVALID_SERVICE }, ++ { "ServiceLimit", "Service limit reached", LOCKDOWN_E_SERVICE_LIMIT }, ++ { "MissingPairRecord", "Missing pair record", LOCKDOWN_E_MISSING_PAIR_RECORD }, ++ { "SavePairRecordFailed", "Saving pair record failed", LOCKDOWN_E_SAVE_PAIR_RECORD_FAILED }, ++ { "InvalidPairRecord", "Invalid pair record", LOCKDOWN_E_INVALID_PAIR_RECORD }, ++ { "InvalidActivationRecord", "Invalid activation record", LOCKDOWN_E_INVALID_ACTIVATION_RECORD }, ++ { "MissingActivationRecord", "Missing activation record", LOCKDOWN_E_MISSING_ACTIVATION_RECORD }, ++ { "ServiceProhibited", "Service prohibited", LOCKDOWN_E_SERVICE_PROHIBITED }, ++ { "EscrowLocked", "Escrow lockded", LOCKDOWN_E_ESCROW_LOCKED }, ++ { "PairingProhibitedOverThisConnection", "Pairing prohibited over this connection", LOCKDOWN_E_PAIRING_PROHIBITED_OVER_THIS_CONNECTION }, ++ { "FMiPProtected", "Find My iPhone/iPod/iPad protected", LOCKDOWN_E_FMIP_PROTECTED }, ++ { "MCProtected", "MC protected" , LOCKDOWN_E_MC_PROTECTED }, ++ { "MCChallengeRequired", "MC challenge required", LOCKDOWN_E_MC_CHALLENGE_REQUIRED }, ++ { NULL, NULL, 0 } ++}; ++ + /** + * Convert an error string identifier to a lockdownd_error_t value. + * Used internally to get correct error codes from a response. +@@ -69,69 +109,13 @@ + static lockdownd_error_t lockdownd_strtoerr(const char* name) + { + lockdownd_error_t err = LOCKDOWN_E_UNKNOWN_ERROR; +- +- if (strcmp(name, "InvalidResponse") == 0) { +- err = LOCKDOWN_E_INVALID_RESPONSE; +- } else if (strcmp(name, "MissingKey") == 0) { +- err = LOCKDOWN_E_MISSING_KEY; +- } else if (strcmp(name, "MissingValue") == 0) { +- err = LOCKDOWN_E_MISSING_VALUE; +- } else if (strcmp(name, "GetProhibited") == 0) { +- err = LOCKDOWN_E_GET_PROHIBITED; +- } else if (strcmp(name, "SetProhibited") == 0) { +- err = LOCKDOWN_E_SET_PROHIBITED; +- } else if (strcmp(name, "RemoveProhibited") == 0) { +- err = LOCKDOWN_E_REMOVE_PROHIBITED; +- } else if (strcmp(name, "ImmutableValue") == 0) { +- err = LOCKDOWN_E_IMMUTABLE_VALUE; +- } else if (strcmp(name, "PasswordProtected") == 0) { +- err = LOCKDOWN_E_PASSWORD_PROTECTED; +- } else if (strcmp(name, "UserDeniedPairing") == 0) { +- err = LOCKDOWN_E_USER_DENIED_PAIRING; +- } else if (strcmp(name, "PairingDialogResponsePending") == 0) { +- err = LOCKDOWN_E_PAIRING_DIALOG_RESPONSE_PENDING; +- } else if (strcmp(name, "MissingHostID") == 0) { +- err = LOCKDOWN_E_MISSING_HOST_ID; +- } else if (strcmp(name, "InvalidHostID") == 0) { +- err = LOCKDOWN_E_INVALID_HOST_ID; +- } else if (strcmp(name, "SessionActive") == 0) { +- err = LOCKDOWN_E_SESSION_ACTIVE; +- } else if (strcmp(name, "SessionInactive") == 0) { +- err = LOCKDOWN_E_SESSION_INACTIVE; +- } else if (strcmp(name, "MissingSessionID") == 0) { +- err = LOCKDOWN_E_MISSING_SESSION_ID; +- } else if (strcmp(name, "InvalidSessionID") == 0) { +- err = LOCKDOWN_E_INVALID_SESSION_ID; +- } else if (strcmp(name, "MissingService") == 0) { +- err = LOCKDOWN_E_MISSING_SERVICE; +- } else if (strcmp(name, "InvalidService") == 0) { +- err = LOCKDOWN_E_INVALID_SERVICE; +- } else if (strcmp(name, "ServiceLimit") == 0) { +- err = LOCKDOWN_E_SERVICE_LIMIT; +- } else if (strcmp(name, "MissingPairRecord") == 0) { +- err = LOCKDOWN_E_MISSING_PAIR_RECORD; +- } else if (strcmp(name, "SavePairRecordFailed") == 0) { +- err = LOCKDOWN_E_SAVE_PAIR_RECORD_FAILED; +- } else if (strcmp(name, "InvalidPairRecord") == 0) { +- err = LOCKDOWN_E_INVALID_PAIR_RECORD; +- } else if (strcmp(name, "InvalidActivationRecord") == 0) { +- err = LOCKDOWN_E_INVALID_ACTIVATION_RECORD; +- } else if (strcmp(name, "MissingActivationRecord") == 0) { +- err = LOCKDOWN_E_MISSING_ACTIVATION_RECORD; +- } else if (strcmp(name, "ServiceProhibited") == 0) { +- err = LOCKDOWN_E_SERVICE_PROHIBITED; +- } else if (strcmp(name, "EscrowLocked") == 0) { +- err = LOCKDOWN_E_ESCROW_LOCKED; +- } else if (strcmp(name, "PairingProhibitedOverThisConnection") == 0) { +- err = LOCKDOWN_E_PAIRING_PROHIBITED_OVER_THIS_CONNECTION; +- } else if (strcmp(name, "FMiPProtected") == 0) { +- err = LOCKDOWN_E_FMIP_PROTECTED; +- } else if (strcmp(name, "MCProtected") == 0) { +- err = LOCKDOWN_E_MC_PROTECTED; +- } else if (strcmp(name, "MCChallengeRequired") == 0) { +- err = LOCKDOWN_E_MC_CHALLENGE_REQUIRED; ++ int i = 0; ++ while (lockdownd_error_str_map[i].lockdown_errstr) { ++ if (strcmp(lockdownd_error_str_map[i].lockdown_errstr, name) == 0) { ++ return lockdownd_error_str_map[i].errcode; ++ } ++ i++; + } +- + return err; + } + +@@ -1541,3 +1525,41 @@ LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_service_descriptor_free(lockdow + + return LOCKDOWN_E_SUCCESS; + } ++ ++LIBIMOBILEDEVICE_API const char* lockdownd_strerror(lockdownd_error_t err) ++{ ++ switch (err) { ++ case LOCKDOWN_E_SUCCESS: ++ return "Success"; ++ case LOCKDOWN_E_INVALID_ARG: ++ return "Invalid argument"; ++ case LOCKDOWN_E_INVALID_CONF: ++ return "Invalid configuration"; ++ case LOCKDOWN_E_PLIST_ERROR: ++ return "PropertyList error"; ++ case LOCKDOWN_E_PAIRING_FAILED: ++ return "Pairing failed"; ++ case LOCKDOWN_E_SSL_ERROR: ++ return "SSL error"; ++ case LOCKDOWN_E_DICT_ERROR: ++ return "Invalid dictionary"; ++ case LOCKDOWN_E_RECEIVE_TIMEOUT: ++ return "Receive timeout"; ++ case LOCKDOWN_E_MUX_ERROR: ++ return "Mux error"; ++ case LOCKDOWN_E_NO_RUNNING_SESSION: ++ return "No running session"; ++ case LOCKDOWN_E_UNKNOWN_ERROR: ++ return "Unknown Error"; ++ default: { ++ int i = 0; ++ while (lockdownd_error_str_map[i].lockdown_errstr) { ++ if (lockdownd_error_str_map[i].errcode == err) { ++ return lockdownd_error_str_map[i].errstr; ++ } ++ i++; ++ } ++ } break; ++ } ++ return "Unknown Error"; ++} +-- +2.23.0 + + +From d6ca8fca11c6aa86ed5fbcf943e1580eb8587538 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Fri, 8 Nov 2019 00:55:59 +0100 +Subject: [PATCH 147/151] tools: Allow ideviceinfo to connect to network + devices + +--- + tools/ideviceinfo.c | 154 +++++++++++++++++++++++++------------------- + 1 file changed, 88 insertions(+), 66 deletions(-) + +diff --git a/tools/ideviceinfo.c b/tools/ideviceinfo.c +index a1124cf..bd3819e 100644 +--- a/tools/ideviceinfo.c ++++ b/tools/ideviceinfo.c +@@ -2,6 +2,7 @@ + * ideviceinfo.c + * Simple utility to show information about an attached device + * ++ * Copyright (c) 2010-2019 Nikias Bassen, All Rights Reserved. + * Copyright (c) 2009 Martin Szulecki All Rights Reserved. + * + * This library is free software; you can redistribute it and/or +@@ -27,6 +28,7 @@ + #include + #include + #include ++#include + #ifndef WIN32 + #include + #endif +@@ -84,28 +86,32 @@ static int is_domain_known(char *domain) + return 0; + } + +-static void print_usage(int argc, char **argv) ++static void print_usage(int argc, char **argv, int is_error) + { + int i = 0; + char *name = NULL; +- + name = strrchr(argv[0], '/'); +- printf("Usage: %s [OPTIONS]\n", (name ? name + 1: argv[0])); +- printf("Show information about a connected device.\n\n"); +- printf(" -d, --debug\t\tenable communication debugging\n"); +- printf(" -s, --simple\t\tuse a simple connection to avoid auto-pairing with the device\n"); +- printf(" -u, --udid UDID\ttarget specific device by UDID\n"); +- printf(" -q, --domain NAME\tset domain of query to NAME. Default: None\n"); +- printf(" -k, --key NAME\tonly query key specified by NAME. Default: All keys.\n"); +- printf(" -x, --xml\t\toutput information as xml plist instead of key/value pairs\n"); +- printf(" -h, --help\t\tprints usage information\n"); +- printf("\n"); +- printf(" Known domains are:\n\n"); ++ fprintf(is_error ? stderr : stdout, "Usage: %s [OPTIONS]\n", (name ? name + 1: argv[0])); ++ fprintf(is_error ? stderr : stdout, ++ "Show information about a connected device.\n\n" \ ++ " -s, --simple use a simple connection to avoid auto-pairing with the device\n" \ ++ " -u, --udid UDID target specific device by UDID\n" \ ++ " -n, --network connect to network device even if available via USB\n" \ ++ " -q, --domain NAME set domain of query to NAME. Default: None\n" \ ++ " -k, --key NAME only query key specified by NAME. Default: All keys.\n" \ ++ " -x, --xml output information as xml plist instead of key/value pairs\n" \ ++ " -h, --help prints usage information\n" \ ++ " -d, --debug enable communication debugging\n" \ ++ "\n" ++ ); ++ fprintf(is_error ? stderr : stdout, " Known domains are:\n\n"); + while (domains[i] != NULL) { +- printf(" %s\n", domains[i++]); ++ fprintf(is_error ? stderr : stdout, " %s\n", domains[i++]); + } +- printf("\n"); +- printf("Homepage: <" PACKAGE_URL ">\n"); ++ fprintf(is_error ? stderr : stdout, ++ "\n" \ ++ "Homepage: <" PACKAGE_URL ">\n" ++ ); + } + + int main(int argc, char *argv[]) +@@ -114,79 +120,91 @@ int main(int argc, char *argv[]) + lockdownd_error_t ldret = LOCKDOWN_E_UNKNOWN_ERROR; + idevice_t device = NULL; + idevice_error_t ret = IDEVICE_E_UNKNOWN_ERROR; +- int i; + int simple = 0; + int format = FORMAT_KEY_VALUE; +- const char* udid = NULL; ++ char* udid = NULL; + char *domain = NULL; + char *key = NULL; + char *xml_doc = NULL; + uint32_t xml_length; + plist_t node = NULL; ++ enum idevice_options lookup_opts = IDEVICE_LOOKUP_USBMUX | IDEVICE_LOOKUP_NETWORK; ++ ++ int c = 0; ++ const struct option longopts[] = { ++ { "debug", no_argument, NULL, 'd' }, ++ { "help", no_argument, NULL, 'h' }, ++ { "udid", required_argument, NULL, 'u' }, ++ { "network", no_argument, NULL, 'n' }, ++ { "domain", required_argument, NULL, 'q' }, ++ { "key", required_argument, NULL, 'k' }, ++ { "xml", no_argument, NULL, 'x' }, ++ { NULL, 0, NULL, 0} ++ }; + + #ifndef WIN32 + signal(SIGPIPE, SIG_IGN); + #endif +- /* parse cmdline args */ +- for (i = 1; i < argc; i++) { +- if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")) { ++ ++ while ((c = getopt_long(argc, argv, "dhu:nq:k:x", longopts, NULL)) != -1) { ++ switch (c) { ++ case 'd': + idevice_set_debug_level(1); +- continue; +- } +- else if (!strcmp(argv[i], "-u") || !strcmp(argv[i], "--udid")) { +- i++; +- if (!argv[i] || !*argv[i]) { +- print_usage(argc, argv); +- return 0; +- } +- udid = argv[i]; +- continue; +- } +- else if (!strcmp(argv[i], "-q") || !strcmp(argv[i], "--domain")) { +- i++; +- if (!argv[i] || (strlen(argv[i]) < 4)) { +- print_usage(argc, argv); +- return 0; ++ break; ++ case 'u': ++ if (!*optarg) { ++ fprintf(stderr, "ERROR: UDID must not be empty!\n"); ++ print_usage(argc, argv, 1); ++ return 2; + } +- if (!is_domain_known(argv[i])) { +- fprintf(stderr, "WARNING: Sending query with unknown domain \"%s\".\n", argv[i]); ++ free(udid); ++ udid = strdup(optarg); ++ break; ++ case 'n': ++ lookup_opts |= IDEVICE_LOOKUP_PREFER_NETWORK; ++ break; ++ case 'q': ++ if (!*optarg) { ++ fprintf(stderr, "ERROR: 'domain' must not be empty!\n"); ++ print_usage(argc, argv, 1); ++ return 2; + } +- domain = strdup(argv[i]); +- continue; +- } +- else if (!strcmp(argv[i], "-k") || !strcmp(argv[i], "--key")) { +- i++; +- if (!argv[i] || (strlen(argv[i]) <= 1)) { +- print_usage(argc, argv); +- return 0; ++ free(domain); ++ domain = strdup(optarg); ++ break; ++ case 'k': ++ if (!*optarg) { ++ fprintf(stderr, "ERROR: 'key' must not be empty!\n"); ++ print_usage(argc, argv, 1); ++ return 2; + } +- key = strdup(argv[i]); +- continue; +- } +- else if (!strcmp(argv[i], "-x") || !strcmp(argv[i], "--xml")) { ++ free(key); ++ key = strdup(optarg); ++ break; ++ case 'x': + format = FORMAT_XML; +- continue; +- } +- else if (!strcmp(argv[i], "-s") || !strcmp(argv[i], "--simple")) { ++ break; ++ case 's': + simple = 1; +- continue; +- } +- else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { +- print_usage(argc, argv); +- return 0; +- } +- else { +- print_usage(argc, argv); ++ break; ++ case 'h': ++ print_usage(argc, argv, 0); + return 0; ++ default: ++ print_usage(argc, argv, 1); ++ return 2; + } + } + +- ret = idevice_new(&device, udid); ++ argc -= optind; ++ argv += optind; ++ ++ ret = idevice_new_with_options(&device, udid, lookup_opts); + if (ret != IDEVICE_E_SUCCESS) { + if (udid) { +- printf("No device found with udid %s, is it plugged in?\n", udid); ++ printf("ERROR: Device %s not found!\n", udid); + } else { +- printf("No device found, is it plugged in?\n"); ++ printf("ERROR: No device found!\n"); + } + return -1; + } +@@ -194,11 +212,15 @@ int main(int argc, char *argv[]) + if (LOCKDOWN_E_SUCCESS != (ldret = simple ? + lockdownd_client_new(device, &client, "ideviceinfo"): + lockdownd_client_new_with_handshake(device, &client, "ideviceinfo"))) { +- fprintf(stderr, "ERROR: Could not connect to lockdownd, error code %d\n", ldret); ++ fprintf(stderr, "ERROR: Could not connect to lockdownd: %s (%d)\n", lockdownd_strerror(ldret), ldret); + idevice_free(device); + return -1; + } + ++ if (domain && !is_domain_known(domain)) { ++ fprintf(stderr, "WARNING: Sending query with unknown domain \"%s\".\n", domain); ++ } ++ + /* run query and output information */ + if(lockdownd_get_value(client, domain, key, &node) == LOCKDOWN_E_SUCCESS) { + if (node) { +-- +2.23.0 + + +From 7dbc17f2c763a7b18bc1a867f39918c26bb5e9e5 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Fri, 8 Nov 2019 00:56:13 +0100 +Subject: [PATCH 148/151] tools: Allow idevicesyslog to connect to network + devices + +--- + tools/idevicesyslog.c | 99 ++++++++++++++++++++++++------------------- + 1 file changed, 55 insertions(+), 44 deletions(-) + +diff --git a/tools/idevicesyslog.c b/tools/idevicesyslog.c +index 76de128..5521736 100644 +--- a/tools/idevicesyslog.c ++++ b/tools/idevicesyslog.c +@@ -2,6 +2,7 @@ + * idevicesyslog.c + * Relay the syslog of a device to stdout + * ++ * Copyright (c) 2010-2019 Nikias Bassen, All Rights Reserved. + * Copyright (c) 2009 Martin Szulecki All Rights Reserved. + * + * This library is free software; you can redistribute it and/or +@@ -29,6 +30,7 @@ + #include + #include + #include ++#include + + #ifdef WIN32 + #include +@@ -40,13 +42,13 @@ + + static int quit_flag = 0; + +-void print_usage(int argc, char **argv); +- + static char* udid = NULL; + + static idevice_t device = NULL; + static syslog_relay_client_t syslog = NULL; + ++enum idevice_options lookup_opts = IDEVICE_LOOKUP_USBMUX | IDEVICE_LOOKUP_NETWORK; ++ + static void syslog_callback(char c, void *user_data) + { + putchar(c); +@@ -57,7 +59,7 @@ static void syslog_callback(char c, void *user_data) + + static int start_logging(void) + { +- idevice_error_t ret = idevice_new(&device, udid); ++ idevice_error_t ret = idevice_new_with_options(&device, udid, lookup_opts); + if (ret != IDEVICE_E_SUCCESS) { + fprintf(stderr, "Device with udid %s not found!?\n", udid); + return -1; +@@ -166,9 +168,31 @@ static void clean_exit(int sig) + quit_flag++; + } + ++static void print_usage(int argc, char **argv, int is_error) ++{ ++ char *name = NULL; ++ name = strrchr(argv[0], '/'); ++ fprintf(is_error ? stderr : stdout, "Usage: %s [OPTIONS]\n", (name ? name + 1: argv[0])); ++ fprintf(is_error ? stderr : stdout, ++ "Relay syslog of a connected device.\n\n" \ ++ " -u, --udid UDID target specific device by UDID\n" \ ++ " -n, --network connect to network device even if available via USB\n" \ ++ " -h, --help prints usage information\n" \ ++ " -d, --debug enable communication debugging\n" \ ++ "\n" \ ++ "Homepage: <" PACKAGE_URL ">\n" ++ ); ++} ++ + int main(int argc, char *argv[]) + { +- int i; ++ int c = 0; ++ const struct option longopts[] = { ++ { "debug", no_argument, NULL, 'd' }, ++ { "help", no_argument, NULL, 'h' }, ++ { "udid", required_argument, NULL, 'u' }, ++ { NULL, 0, NULL, 0} ++ }; + + signal(SIGINT, clean_exit); + signal(SIGTERM, clean_exit); +@@ -177,35 +201,39 @@ int main(int argc, char *argv[]) + signal(SIGPIPE, SIG_IGN); + #endif + +- /* parse cmdline args */ +- for (i = 1; i < argc; i++) { +- if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--debug")) { ++ while ((c = getopt_long(argc, argv, "dhu:n", longopts, NULL)) != -1) { ++ switch (c) { ++ case 'd': + idevice_set_debug_level(1); +- continue; +- } +- else if (!strcmp(argv[i], "-u") || !strcmp(argv[i], "--udid")) { +- i++; +- if (!argv[i] || !*argv[i]) { +- print_usage(argc, argv); +- return 0; ++ break; ++ case 'u': ++ if (!*optarg) { ++ fprintf(stderr, "ERROR: UDID must not be empty!\n"); ++ print_usage(argc, argv, 1); ++ return 2; + } +- udid = strdup(argv[i]); +- continue; +- } +- else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { +- print_usage(argc, argv); +- return 0; +- } +- else { +- print_usage(argc, argv); ++ free(udid); ++ udid = strdup(optarg); ++ break; ++ case 'n': ++ lookup_opts |= IDEVICE_LOOKUP_PREFER_NETWORK; ++ break; ++ case 'h': ++ print_usage(argc, argv, 0); + return 0; ++ default: ++ print_usage(argc, argv, 1); ++ return 2; + } + } + ++ argc -= optind; ++ argv += optind; ++ + int num = 0; +- char **devices = NULL; +- idevice_get_device_list(&devices, &num); +- idevice_device_list_free(devices); ++ idevice_info_t *devices = NULL; ++ idevice_get_device_list_extended(&devices, &num); ++ idevice_device_list_extended_free(devices); + if (num == 0) { + if (!udid) { + fprintf(stderr, "No device found. Plug in a device or pass UDID with -u to wait for device to be available.\n"); +@@ -223,24 +251,7 @@ int main(int argc, char *argv[]) + idevice_event_unsubscribe(); + stop_logging(); + +- if (udid) { +- free(udid); +- } ++ free(udid); + + return 0; + } +- +-void print_usage(int argc, char **argv) +-{ +- char *name = NULL; +- +- name = strrchr(argv[0], '/'); +- printf("Usage: %s [OPTIONS]\n", (name ? name + 1: argv[0])); +- printf("Relay syslog of a connected device.\n\n"); +- printf(" -d, --debug\t\tenable communication debugging\n"); +- printf(" -u, --udid UDID\ttarget specific device by UDID\n"); +- printf(" -h, --help\t\tprints usage information\n"); +- printf("\n"); +- printf("Homepage: <" PACKAGE_URL ">\n"); +-} +- +-- +2.23.0 + + +From af91dc6376946daffd5c9ece916d9f33af828890 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Wed, 13 Nov 2019 09:06:41 +0100 +Subject: [PATCH 149/151] debugserver: Improved memory handling in + debugserver_client_send_command() and debugserver_client_receive_response() + +--- + common/utils.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++- + common/utils.h | 6 +++++- + src/debugserver.c | 47 +++++++++++++++++++++++---------------------- + 3 files changed, 77 insertions(+), 25 deletions(-) + +diff --git a/common/utils.c b/common/utils.c +index 4a45d95..7f66ec2 100644 +--- a/common/utils.c ++++ b/common/utils.c +@@ -1,7 +1,10 @@ + /* + * utils.c +- * Miscellaneous utilities for string manipulation ++ * Miscellaneous utilities for string manipulation, ++ * file I/O and plist helper. + * ++ * Copyright (c) 2014-2019 Nikias Bassen, All Rights Reserved. ++ * Copyright (c) 2013-2014 Martin Szulecki, All Rights Reserved. + * Copyright (c) 2013 Federico Mena Quintero + * + * This library is free software; you can redistribute it and/or +@@ -111,6 +114,50 @@ char *string_concat(const char *str, ...) + return result; + } + ++char *string_append(char* str, ...) ++{ ++ size_t len = 0; ++ size_t slen; ++ va_list args; ++ char *s; ++ char *result; ++ char *dest; ++ ++ /* Compute final length */ ++ ++ if (str) { ++ len = strlen(str); ++ } ++ slen = len; ++ len++; /* plus 1 for the null terminator */ ++ ++ va_start(args, str); ++ s = va_arg(args, char *); ++ while (s) { ++ len += strlen(s); ++ s = va_arg(args, char*); ++ } ++ va_end(args); ++ ++ result = realloc(str, len); ++ if (!result) ++ return NULL; /* errno remains set */ ++ ++ dest = result + slen; ++ ++ /* Concat additional strings */ ++ ++ va_start(args, str); ++ s = va_arg(args, char *); ++ while (s) { ++ dest = stpcpy(dest, s); ++ s = va_arg(args, char *); ++ } ++ va_end(args); ++ ++ return result; ++} ++ + char *string_build_path(const char *elem, ...) + { + if (!elem) +diff --git a/common/utils.h b/common/utils.h +index 8426bc0..2c3acec 100644 +--- a/common/utils.h ++++ b/common/utils.h +@@ -1,7 +1,10 @@ + /* + * utils.h +- * Miscellaneous utilities for string manipulation ++ * Miscellaneous utilities for string manipulation, ++ * file I/O and plist helper. + * ++ * Copyright (c) 2014-2019 Nikias Bassen, All Rights Reserved. ++ * Copyright (c) 2013-2014 Martin Szulecki, All Rights Reserved. + * Copyright (c) 2013 Federico Mena Quintero + * + * This library is free software; you can redistribute it and/or +@@ -39,6 +42,7 @@ + char *stpcpy(char *s1, const char *s2); + #endif + char *string_concat(const char *str, ...); ++char *string_append(char *str, ...); + char *string_build_path(const char *elem, ...); + char *string_format_size(uint64_t size); + char *string_toupper(char *str); +diff --git a/src/debugserver.c b/src/debugserver.c +index 1e06233..967d01d 100644 +--- a/src/debugserver.c ++++ b/src/debugserver.c +@@ -2,7 +2,8 @@ + * debugserver.c + * com.apple.debugserver service implementation. + * +- * Copyright (c) 2014 Martin Szulecki All Rights Reserved. ++ * Copyright (c) 2019 Nikias Bassen, All Rights Reserved. ++ * Copyright (c) 2014-2015 Martin Szulecki All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public +@@ -378,6 +379,7 @@ LIBIMOBILEDEVICE_API debugserver_error_t debugserver_client_receive_response(deb + + char* buffer = NULL; + uint32_t buffer_size = 0; ++ uint32_t buffer_capacity = 0; + + if (response) + *response = NULL; +@@ -390,7 +392,9 @@ LIBIMOBILEDEVICE_API debugserver_error_t debugserver_client_receive_response(deb + if (strncmp(ack, command_prefix, sizeof(char)) == 0) { + should_receive = 1; + skip_prefix = 1; +- buffer = strdup(command_prefix); ++ buffer = malloc(1024); ++ buffer_capacity = 1024; ++ strcpy(buffer, command_prefix); + buffer_size += sizeof(char); + debug_info("received ACK"); + } +@@ -404,9 +408,11 @@ LIBIMOBILEDEVICE_API debugserver_error_t debugserver_client_receive_response(deb + debug_info("received command_prefix: %c", *command_prefix); + if (should_receive) { + if (buffer) { +- memcpy(buffer, command_prefix, sizeof(char)); ++ strcpy(buffer, command_prefix); + } else { +- buffer = strdup(command_prefix); ++ buffer = malloc(1024); ++ buffer_capacity = 1024; ++ strcpy(buffer, command_prefix); + buffer_size += sizeof(char); + } + } +@@ -418,6 +424,7 @@ LIBIMOBILEDEVICE_API debugserver_error_t debugserver_client_receive_response(deb + uint32_t checksum_length = DEBUGSERVER_CHECKSUM_HASH_LENGTH; + int receiving_checksum_response = 0; + debug_info("attempting to read up response until checksum"); ++ + while ((checksum_length > 0)) { + char data[2] = {'#', '\0'}; + if (debugserver_client_receive_internal_check(client, data)) { +@@ -426,16 +433,20 @@ LIBIMOBILEDEVICE_API debugserver_error_t debugserver_client_receive_response(deb + if (receiving_checksum_response) { + checksum_length--; + } +- char* newbuffer = string_concat(buffer, data, NULL); ++ if (buffer_size + 1 >= buffer_capacity) { ++ char* newbuffer = realloc(buffer, buffer_capacity+1024); ++ if (!newbuffer) { ++ return DEBUGSERVER_E_UNKNOWN_ERROR; ++ } ++ buffer = newbuffer; ++ buffer[buffer_capacity] = '\0'; ++ buffer_capacity += 1024; ++ } ++ strcat(buffer, data); + buffer_size += sizeof(char); +- free(buffer); +- buffer = NULL; +- buffer = newbuffer; +- newbuffer = NULL; + } + debug_info("validating response checksum..."); +- int valid_response = debugserver_response_is_checksum_valid(buffer, buffer_size); +- if (valid_response) { ++ if (client->noack_mode || debugserver_response_is_checksum_valid(buffer, buffer_size)) { + if (response) { + /* assemble response string */ + uint32_t response_size = sizeof(char) * (buffer_size - DEBUGSERVER_CHECKSUM_HASH_LENGTH - 1); +@@ -482,25 +493,15 @@ LIBIMOBILEDEVICE_API debugserver_error_t debugserver_client_send_command(debugse + char* command_arguments = NULL; + + /* concat all arguments */ +- char* tmp = NULL; +- char* newtmp = NULL; + for (i = 0; i < command->argc; i++) { + debug_info("argv[%d]: %s", i, command->argv[i]); +- if (!tmp) { +- tmp = strdup(command->argv[i]); +- } else { +- newtmp = string_concat(tmp, command->argv[i], NULL); +- free(tmp); +- tmp = newtmp; +- } ++ command_arguments = string_append(command_arguments, command->argv[i], NULL); + } +- command_arguments = tmp; +- tmp = NULL; + + debug_info("command_arguments(%d): %s", command->argc, command_arguments); + + /* encode command arguments, add checksum if required and assemble entire command */ +- debugserver_format_command("$", command->name, command_arguments, !client->noack_mode, &send_buffer, &send_buffer_size); ++ debugserver_format_command("$", command->name, command_arguments, 1, &send_buffer, &send_buffer_size); + + debug_info("sending encoded command: %s", send_buffer); + +-- +2.23.0 + + +From 43852c74160394c0be876945b85c0656fa2bff81 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Wed, 20 Nov 2019 01:39:46 +0100 +Subject: [PATCH 150/151] debugserver: Return size of the returned buffer + +--- + include/libimobiledevice/debugserver.h | 6 ++++-- + src/debugserver.c | 19 ++++++++++--------- + tools/idevicedebug.c | 20 ++++++++++---------- + 3 files changed, 24 insertions(+), 21 deletions(-) + +diff --git a/include/libimobiledevice/debugserver.h b/include/libimobiledevice/debugserver.h +index 19a4f5d..8ac116c 100644 +--- a/include/libimobiledevice/debugserver.h ++++ b/include/libimobiledevice/debugserver.h +@@ -142,22 +142,24 @@ debugserver_error_t debugserver_client_receive(debugserver_client_t client, char + * @param client The debugserver client + * @param command Command to process and send + * @param response Response received for the command (can be NULL to ignore) ++ * @param response_size Pointer to receive response size. Set to NULL to ignore. + * + * @return DEBUGSERVER_E_SUCCESS on success, + * DEBUGSERVER_E_INVALID_ARG when client or command is NULL + */ +-debugserver_error_t debugserver_client_send_command(debugserver_client_t client, debugserver_command_t command, char** response); ++debugserver_error_t debugserver_client_send_command(debugserver_client_t client, debugserver_command_t command, char** response, size_t* response_size); + + /** + * Receives and parses response of debugserver service. + * + * @param client The debugserver client + * @param response Response received for last command (can be NULL to ignore) ++ * @param response_size Pointer to receive response size. Set to NULL to ignore. + * + * @return DEBUGSERVER_E_SUCCESS on success, + * DEBUGSERVER_E_INVALID_ARG when client is NULL + */ +-debugserver_error_t debugserver_client_receive_response(debugserver_client_t client, char** response); ++debugserver_error_t debugserver_client_receive_response(debugserver_client_t client, char** response, size_t* response_size); + + /** + * Controls status of ACK mode when sending commands or receiving responses. +diff --git a/src/debugserver.c b/src/debugserver.c +index 967d01d..0b0d614 100644 +--- a/src/debugserver.c ++++ b/src/debugserver.c +@@ -369,7 +369,7 @@ static int debugserver_client_receive_internal_check(debugserver_client_t client + return did_receive_char; + } + +-LIBIMOBILEDEVICE_API debugserver_error_t debugserver_client_receive_response(debugserver_client_t client, char** response) ++LIBIMOBILEDEVICE_API debugserver_error_t debugserver_client_receive_response(debugserver_client_t client, char** response, size_t* response_size) + { + debugserver_error_t res = DEBUGSERVER_E_SUCCESS; + +@@ -449,10 +449,11 @@ LIBIMOBILEDEVICE_API debugserver_error_t debugserver_client_receive_response(deb + if (client->noack_mode || debugserver_response_is_checksum_valid(buffer, buffer_size)) { + if (response) { + /* assemble response string */ +- uint32_t response_size = sizeof(char) * (buffer_size - DEBUGSERVER_CHECKSUM_HASH_LENGTH - 1); +- *response = (char*)malloc(response_size + 1); +- memcpy(*response, buffer + 1, response_size); +- (*response)[response_size] = '\0'; ++ uint32_t resp_size = sizeof(char) * (buffer_size - DEBUGSERVER_CHECKSUM_HASH_LENGTH - 1); ++ *response = (char*)malloc(resp_size + 1); ++ memcpy(*response, buffer + 1, resp_size); ++ (*response)[resp_size] = '\0'; ++ if (response_size) *response_size = resp_size; + } + if (!client->noack_mode) { + /* confirm valid command */ +@@ -481,7 +482,7 @@ LIBIMOBILEDEVICE_API debugserver_error_t debugserver_client_receive_response(deb + return res; + } + +-LIBIMOBILEDEVICE_API debugserver_error_t debugserver_client_send_command(debugserver_client_t client, debugserver_command_t command, char** response) ++LIBIMOBILEDEVICE_API debugserver_error_t debugserver_client_send_command(debugserver_client_t client, debugserver_command_t command, char** response, size_t* response_size) + { + debugserver_error_t res = DEBUGSERVER_E_SUCCESS; + int i; +@@ -512,7 +513,7 @@ LIBIMOBILEDEVICE_API debugserver_error_t debugserver_client_send_command(debugse + } + + /* receive response */ +- res = debugserver_client_receive_response(client, response); ++ res = debugserver_client_receive_response(client, response, response_size); + debug_info("response result: %d", res); + if (res != DEBUGSERVER_E_SUCCESS) { + goto cleanup; +@@ -548,7 +549,7 @@ LIBIMOBILEDEVICE_API debugserver_error_t debugserver_client_set_environment_hex_ + + debugserver_command_t command = NULL; + debugserver_command_new("QEnvironmentHexEncoded:", 1, env_arg, &command); +- result = debugserver_client_send_command(client, command, response); ++ result = debugserver_client_send_command(client, command, response, NULL); + debugserver_command_free(command); + + free(env_tmp); +@@ -617,7 +618,7 @@ LIBIMOBILEDEVICE_API debugserver_error_t debugserver_client_set_argv(debugserver + + debugserver_command_t command = NULL; + debugserver_command_new(pkt, 0, NULL, &command); +- result = debugserver_client_send_command(client, command, response); ++ result = debugserver_client_send_command(client, command, response, NULL); + debugserver_command_free(command); + + if (pkt) +diff --git a/tools/idevicedebug.c b/tools/idevicedebug.c +index c7508e3..6c2f5cf 100644 +--- a/tools/idevicedebug.c ++++ b/tools/idevicedebug.c +@@ -127,7 +127,7 @@ static debugserver_error_t debugserver_client_handle_response(debugserver_client + + /* send reply */ + debugserver_command_new("OK", 0, NULL, &command); +- dres = debugserver_client_send_command(client, command, response); ++ dres = debugserver_client_send_command(client, command, response, NULL); + debug_info("result: %d", dres); + debugserver_command_free(command); + command = NULL; +@@ -153,7 +153,7 @@ static debugserver_error_t debugserver_client_handle_response(debugserver_client + + /* send reply */ + debugserver_command_new("OK", 0, NULL, &command); +- dres = debugserver_client_send_command(client, command, response); ++ dres = debugserver_client_send_command(client, command, response, NULL); + debug_info("result: %d", dres); + debugserver_command_free(command); + command = NULL; +@@ -166,7 +166,7 @@ static debugserver_error_t debugserver_client_handle_response(debugserver_client + + /* no command */ + debugserver_command_new("OK", 0, NULL, &command); +- dres = debugserver_client_send_command(client, command, response); ++ dres = debugserver_client_send_command(client, command, response, NULL); + debug_info("result: %d", dres); + debugserver_command_free(command); + command = NULL; +@@ -342,7 +342,7 @@ int main(int argc, char *argv[]) + if (debug_level) { + debug_info("Setting logging bitmask..."); + debugserver_command_new("QSetLogging:bitmask=LOG_ALL|LOG_RNB_REMOTE|LOG_RNB_PACKETS", 0, NULL, &command); +- dres = debugserver_client_send_command(debugserver_client, command, &response); ++ dres = debugserver_client_send_command(debugserver_client, command, &response, NULL); + debugserver_command_free(command); + command = NULL; + if (response) { +@@ -360,7 +360,7 @@ int main(int argc, char *argv[]) + char* packet_size[2] = {strdup("1024"), NULL}; + debugserver_command_new("QSetMaxPacketSize:", 1, packet_size, &command); + free(packet_size[0]); +- dres = debugserver_client_send_command(debugserver_client, command, &response); ++ dres = debugserver_client_send_command(debugserver_client, command, &response, NULL); + debugserver_command_free(command); + command = NULL; + if (response) { +@@ -376,7 +376,7 @@ int main(int argc, char *argv[]) + debug_info("Setting working directory..."); + char* working_dir[2] = {working_directory, NULL}; + debugserver_command_new("QSetWorkingDir:", 1, working_dir, &command); +- dres = debugserver_client_send_command(debugserver_client, command, &response); ++ dres = debugserver_client_send_command(debugserver_client, command, &response, NULL); + debugserver_command_free(command); + command = NULL; + if (response) { +@@ -417,7 +417,7 @@ int main(int argc, char *argv[]) + /* check if launch succeeded */ + debug_info("Checking if launch succeeded..."); + debugserver_command_new("qLaunchSuccess", 0, NULL, &command); +- dres = debugserver_client_send_command(debugserver_client, command, &response); ++ dres = debugserver_client_send_command(debugserver_client, command, &response, NULL); + debugserver_command_free(command); + command = NULL; + if (response) { +@@ -432,7 +432,7 @@ int main(int argc, char *argv[]) + /* set thread */ + debug_info("Setting thread..."); + debugserver_command_new("Hc0", 0, NULL, &command); +- dres = debugserver_client_send_command(debugserver_client, command, &response); ++ dres = debugserver_client_send_command(debugserver_client, command, &response, NULL); + debugserver_command_free(command); + command = NULL; + if (response) { +@@ -447,7 +447,7 @@ int main(int argc, char *argv[]) + /* continue running process */ + debug_info("Continue running process..."); + debugserver_command_new("c", 0, NULL, &command); +- dres = debugserver_client_send_command(debugserver_client, command, &response); ++ dres = debugserver_client_send_command(debugserver_client, command, &response, NULL); + debugserver_command_free(command); + command = NULL; + +@@ -470,7 +470,7 @@ int main(int argc, char *argv[]) + /* kill process after we finished */ + debug_info("Killing process..."); + debugserver_command_new("k", 0, NULL, &command); +- dres = debugserver_client_send_command(debugserver_client, command, &response); ++ dres = debugserver_client_send_command(debugserver_client, command, &response, NULL); + debugserver_command_free(command); + command = NULL; + if (response) { +-- +2.23.0 + + +From 9b857fc42cdc4921e1e3f190c5ea907774e04758 Mon Sep 17 00:00:00 2001 +From: Nikias Bassen +Date: Wed, 20 Nov 2019 01:40:08 +0100 +Subject: [PATCH 151/151] tools: Fix ideviceinfo -s option + +--- + tools/ideviceinfo.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/tools/ideviceinfo.c b/tools/ideviceinfo.c +index bd3819e..f52cd00 100644 +--- a/tools/ideviceinfo.c ++++ b/tools/ideviceinfo.c +@@ -138,6 +138,7 @@ int main(int argc, char *argv[]) + { "network", no_argument, NULL, 'n' }, + { "domain", required_argument, NULL, 'q' }, + { "key", required_argument, NULL, 'k' }, ++ { "simple", no_argument, NULL, 's' }, + { "xml", no_argument, NULL, 'x' }, + { NULL, 0, NULL, 0} + }; +@@ -146,7 +147,7 @@ int main(int argc, char *argv[]) + signal(SIGPIPE, SIG_IGN); + #endif + +- while ((c = getopt_long(argc, argv, "dhu:nq:k:x", longopts, NULL)) != -1) { ++ while ((c = getopt_long(argc, argv, "dhu:nq:k:sx", longopts, NULL)) != -1) { + switch (c) { + case 'd': + idevice_set_debug_level(1); +-- +2.23.0 + diff --git a/libimobiledevice.spec b/libimobiledevice.spec index b016f7f..ae469e8 100644 --- a/libimobiledevice.spec +++ b/libimobiledevice.spec @@ -1,18 +1,18 @@ Name: libimobiledevice -Version: 1.2.0 -Release: 19%{?dist} +Version: 1.2.1 +Release: 0.1%{?dist} Summary: Library for connecting to mobile devices License: LGPLv2+ URL: http://www.libimobiledevice.org/ -Source0: http://www.libimobiledevice.org/downloads/%{name}-%{version}.tar.bz2 +Source0: http://www.libimobiledevice.org/downloads/%{name}-1.2.0.tar.bz2 # Upstream patches, generated with: -# git format-patch --stdout 344409e1d1ad917d377b256214c5411dda82e6b0...5a85432719fb3d18027d528f87d2a44b76fd3e12 -# b5a70e9aaf538dad0aba0b800b122955e8ac494b was manually removed -Patch0: 344409e1d1ad917d377b256214c5411dda82e6b0...5a85432719fb3d18027d528f87d2a44b76fd3e12.patch -# GNUTLS 3.6.0 bug fixes -Patch1: 0001-userpref-GnuTLS-Fix-3.6.0-SHA1-compatibility.patch -Patch2: 0002-userpref-GnuTLS-Use-valid-serial-for-3.6.0.patch +# git format-patch --stdout 344409e1d1ad917d377b256214c5411dda82e6b0...9b857fc42cdc4921e1e3f190c5ea907774e04758 +# b5a70e9aaf538dad0aba0b800b122955e8ac494b +# 26373b334889f5ae2e2737ff447eb25b1700fa2f +# 97f8ac9e9ad9ee73ca635a26831bfe950a5d673b +# were manually removed +Patch0: a7568f456d10f1aff61534e3216201a857865247...9b857fc42cdc4921e1e3f190c5ea907774e04758.patch BuildRequires: glib2-devel BuildRequires: gnutls-devel @@ -46,7 +46,7 @@ Requires: %{name}%{?_isa} = %{version}-%{release} Utilites for use with libimobiledevice. %prep -%autosetup -S git +%autosetup -S git_am -n %{name}-1.2.0 # Fix dir permissions on html docs chmod +x docs/html @@ -72,7 +72,7 @@ find %{buildroot} -type f -name "*.la" -delete %files %{!?_licensedir:%global license %%doc} %license COPYING.LESSER -%doc AUTHORS README +%doc AUTHORS README.md %{_libdir}/libimobiledevice.so.6* %files utils @@ -86,6 +86,11 @@ find %{buildroot} -type f -name "*.la" -delete %{_includedir}/libimobiledevice/ %changelog +* Mon Nov 25 2019 Bastien Nocera - 1.2.1-0.1 ++ libimobiledevice-1.2.1-0.1 +- Add support for newer devices +- This is a snapshot of the in-development 1.2.1 version + * Thu Jul 25 2019 Fedora Release Engineering - 1.2.0-19 - Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild