Hello community, here is the log from the commit of package libimobiledevice for openSUSE:Factory checked in at 2018-06-22 13:13:38 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/libimobiledevice (Old) and /work/SRC/openSUSE:Factory/.libimobiledevice.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "libimobiledevice" Fri Jun 22 13:13:38 2018 rev:37 rq:616171 version:1.2.0+git20180427.26373b3 Changes: -------- --- /work/SRC/openSUSE:Factory/libimobiledevice/libimobiledevice.changes 2017-02-08 10:43:07.716861555 +0100 +++ /work/SRC/openSUSE:Factory/.libimobiledevice.new/libimobiledevice.changes 2018-06-22 13:13:38.366917511 +0200 @@ -1,0 +2,27 @@ +Tue Jun 12 01:28:19 UTC 2018 - i...@marguerite.su + +- update version 1.2.0+git20180427.26373b3 + * Propagate lower level errors to callers instead of returning unknown + * Added IDEVICE_DEVICE_PAIRED event constant matching the corresponding + * Define htobe16 if not defined + * Fix parameter check of instproxy_check_capabilities_match() + * Avoid double free with OpenSSL 1.1.0 + * Don't use ERR_remove_thread_state() with OpenSSL 1.1.0 + * #ifdef out code which is a no-op with OpenSSL 1.1.0 + * cython: Fix build error after error constant rename + * gnutls: check for interrupted gnutls_handshake() + * idevicescreenshot: Detect screenshot image format to determine file extension + * Add basic mobileactivation service implementation + * mobileactivation: Add new functions required for drmHandshake / session mode device activation + * lockdown: Don't explicitly validate pairing unless we're dealing with an older device + * mobileactivation: Don't convert activation record if it is already passed as PLIST_DATA + * mobileactivation: Allow passing activation response headers as required for iOS 11.2+ + * lockdown: Plug small memory leak + * idevicesyslog: Wait for passcode entry on device when required + * idevicediagnostics: Add HDMI to the list of valid options for diagnostics command + * idevicediagnostics: Add ioregentry command to query device IORegistry by entry + * userpref: [GnuTLS] Fix 3.6.0 SHA1 compatibility + * userpref: [GnuTLS] Use valid serial for >= 3.6.0 + * build: Fix autogen.sh with srcdir != builddir + +------------------------------------------------------------------- Old: ---- libimobiledevice-1.2.0+git20170122.45fda81.tar.xz New: ---- libimobiledevice-1.2.0+git20180427.26373b3.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ libimobiledevice.spec ++++++ --- /var/tmp/diff_new_pack.R7VbkB/_old 2018-06-22 13:13:39.142888736 +0200 +++ /var/tmp/diff_new_pack.R7VbkB/_new 2018-06-22 13:13:39.146888588 +0200 @@ -18,7 +18,7 @@ %define soname 6 Name: libimobiledevice -Version: 1.2.0+git20170122.45fda81 +Version: 1.2.0+git20180427.26373b3 Release: 0 Summary: Native protocols library for iOS devices License: LGPL-2.1+ ++++++ libimobiledevice-1.2.0+git20170122.45fda81.tar.xz -> libimobiledevice-1.2.0+git20180427.26373b3.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libimobiledevice-1.2.0+git20170122.45fda81/README new/libimobiledevice-1.2.0+git20180427.26373b3/README --- old/libimobiledevice-1.2.0+git20170122.45fda81/README 2017-01-22 13:28:45.551033668 +0100 +++ new/libimobiledevice-1.2.0+git20180427.26373b3/README 2018-04-27 19:24:36.000000000 +0200 @@ -8,7 +8,7 @@ ============ Development Packages of: - libgnutls or openssl + OpenSSL or GnuTLS libplist libusbmuxd @@ -20,7 +20,7 @@ autoconf libtool pkg-config - gcc + gcc or clang Optional: cython (Python bindings) @@ -34,6 +34,16 @@ 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 @@ 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 @@ authorized, sponsored, or otherwise approved by Apple Inc. README Updated on: - 2015-01-28 + 2017-04-28 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libimobiledevice-1.2.0+git20170122.45fda81/autogen.sh new/libimobiledevice-1.2.0+git20180427.26373b3/autogen.sh --- old/libimobiledevice-1.2.0+git20170122.45fda81/autogen.sh 2017-01-22 13:28:45.551033668 +0100 +++ new/libimobiledevice-1.2.0+git20180427.26373b3/autogen.sh 2018-04-27 19:24:36.000000000 +0200 @@ -1,4 +1,11 @@ #!/bin/sh + +olddir=`pwd` +srcdir=`dirname $0` +test -z "$srcdir" && srcdir=. + +cd "$srcdir" + gprefix=`which glibtoolize 2>&1 >/dev/null` if [ $? -eq 0 ]; then glibtoolize --force @@ -10,6 +17,8 @@ automake --add-missing autoconf +cd "$olddir" + if [ -z "$NOCONFIGURE" ]; then - ./configure "$@" + $srcdir/configure "$@" fi diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libimobiledevice-1.2.0+git20170122.45fda81/common/userpref.c new/libimobiledevice-1.2.0+git20180427.26373b3/common/userpref.c --- old/libimobiledevice-1.2.0+git20170122.45fda81/common/userpref.c 2017-01-22 13:28:45.555033668 +0100 +++ new/libimobiledevice-1.2.0+git20180427.26373b3/common/userpref.c 2018-04-27 19:24:36.000000000 +0200 @@ -598,21 +598,21 @@ /* 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)); 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); + 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); 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; @@ -703,7 +703,7 @@ 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)); @@ -720,7 +720,7 @@ } 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; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libimobiledevice-1.2.0+git20170122.45fda81/cython/lockdown.pxi new/libimobiledevice-1.2.0+git20180427.26373b3/cython/lockdown.pxi --- old/libimobiledevice-1.2.0+git20170122.45fda81/cython/lockdown.pxi 2017-01-22 13:28:45.555033668 +0100 +++ new/libimobiledevice-1.2.0+git20180427.26373b3/cython/lockdown.pxi 2018-04-27 19:24:36.000000000 +0200 @@ -7,7 +7,7 @@ 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 @@ 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", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libimobiledevice-1.2.0+git20170122.45fda81/include/Makefile.am new/libimobiledevice-1.2.0+git20180427.26373b3/include/Makefile.am --- old/libimobiledevice-1.2.0+git20170122.45fda81/include/Makefile.am 2017-01-22 13:28:45.555033668 +0100 +++ new/libimobiledevice-1.2.0+git20180427.26373b3/include/Makefile.am 2018-04-27 19:24:36.000000000 +0200 @@ -20,5 +20,6 @@ libimobiledevice/diagnostics_relay.h\ libimobiledevice/debugserver.h\ libimobiledevice/syslog_relay.h\ + libimobiledevice/mobileactivation.h\ libimobiledevice/property_list_service.h\ libimobiledevice/service.h diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libimobiledevice-1.2.0+git20170122.45fda81/include/endianness.h new/libimobiledevice-1.2.0+git20180427.26373b3/include/endianness.h --- old/libimobiledevice-1.2.0+git20170122.45fda81/include/endianness.h 2017-01-22 13:28:45.555033668 +0100 +++ new/libimobiledevice-1.2.0+git20180427.26373b3/include/endianness.h 2018-04-27 19:24:36.000000000 +0200 @@ -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) \ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libimobiledevice-1.2.0+git20170122.45fda81/include/libimobiledevice/libimobiledevice.h new/libimobiledevice-1.2.0+git20180427.26373b3/include/libimobiledevice/libimobiledevice.h --- old/libimobiledevice-1.2.0+git20170122.45fda81/include/libimobiledevice/libimobiledevice.h 2017-01-22 13:28:45.559033668 +0100 +++ new/libimobiledevice-1.2.0+git20180427.26373b3/include/libimobiledevice/libimobiledevice.h 2018-04-27 19:24:36.000000000 +0200 @@ -55,7 +55,8 @@ /** 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 */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libimobiledevice-1.2.0+git20170122.45fda81/include/libimobiledevice/lockdown.h new/libimobiledevice-1.2.0+git20180427.26373b3/include/libimobiledevice/lockdown.h --- old/libimobiledevice-1.2.0+git20170122.45fda81/include/libimobiledevice/lockdown.h 2017-01-22 13:28:45.559033668 +0100 +++ new/libimobiledevice-1.2.0+git20180427.26373b3/include/libimobiledevice/lockdown.h 2018-04-27 19:24:36.000000000 +0200 @@ -43,7 +43,7 @@ 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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libimobiledevice-1.2.0+git20170122.45fda81/include/libimobiledevice/mobileactivation.h new/libimobiledevice-1.2.0+git20180427.26373b3/include/libimobiledevice/mobileactivation.h --- old/libimobiledevice-1.2.0+git20170122.45fda81/include/libimobiledevice/mobileactivation.h 1970-01-01 01:00:00.000000000 +0100 +++ new/libimobiledevice-1.2.0+git20180427.26373b3/include/libimobiledevice/mobileactivation.h 2018-04-27 19:24:36.000000000 +0200 @@ -0,0 +1,191 @@ +/** + * @file libimobiledevice/mobileactivation.h + * @brief Handle device activation and deactivation. + * \internal + * + * 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 + * 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 <libimobiledevice/libimobiledevice.h> +#include <libimobiledevice/lockdown.h> + +#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 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. + * + * @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); + +/** + * 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 + * 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); + +/** + * Activates the device with the given activation record in 'session' mode. + * 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 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, plist_t headers); + +/** + * Deactivates the device. + * + * @param client The mobileactivation client + */ +mobileactivation_error_t mobileactivation_deactivate(mobileactivation_client_t client); + +#ifdef __cplusplus +} +#endif + +#endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libimobiledevice-1.2.0+git20170122.45fda81/src/Makefile.am new/libimobiledevice-1.2.0+git20180427.26373b3/src/Makefile.am --- old/libimobiledevice-1.2.0+git20170122.45fda81/src/Makefile.am 2017-01-22 13:28:45.559033668 +0100 +++ new/libimobiledevice-1.2.0+git20180427.26373b3/src/Makefile.am 2018-04-27 19:24:36.000000000 +0200 @@ -28,6 +28,7 @@ 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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libimobiledevice-1.2.0+git20170122.45fda81/src/idevice.c new/libimobiledevice-1.2.0+git20180427.26373b3/src/idevice.c --- old/libimobiledevice-1.2.0+git20170122.45fda81/src/idevice.c 2017-01-22 13:28:45.559033668 +0100 +++ new/libimobiledevice-1.2.0+git20180427.26373b3/src/idevice.c 2018-04-27 19:24:36.000000000 +0200 @@ -37,10 +37,7 @@ #ifdef HAVE_OPENSSL #include <openssl/err.h> #include <openssl/ssl.h> -#if OPENSSL_VERSION_NUMBER >= 0x10000001L -/* since OpenSSL 1.0.0-beta1 */ -#define HAVE_ERR_REMOVE_THREAD_STATE 1 -#endif + #else #include <gnutls/gnutls.h> #endif @@ -51,6 +48,28 @@ #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 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 +} + +#if OPENSSL_VERSION_NUMBER < 0x10100000L static mutex_t *mutex_buf = NULL; static void locking_function(int mode, int n, const char* file, int line) { @@ -65,10 +84,12 @@ 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(); @@ -80,6 +101,7 @@ CRYPTO_set_id_callback(id_function); CRYPTO_set_locking_callback(locking_function); +#endif #else gnutls_global_init(); #endif @@ -88,6 +110,7 @@ static void internal_idevice_deinit(void) { #ifdef HAVE_OPENSSL +#if OPENSSL_VERSION_NUMBER < 0x10100000L int i; if (mutex_buf) { CRYPTO_set_id_callback(NULL); @@ -100,11 +123,8 @@ EVP_cleanup(); CRYPTO_cleanup_all_ex_data(); - sk_SSL_COMP_free(SSL_COMP_get_compression_methods()); -#ifdef HAVE_ERR_REMOVE_THREAD_STATE - ERR_remove_thread_state(NULL); -#else - ERR_remove_state(0); + SSL_COMP_free_compression_methods(); + openssl_remove_thread_state(); #endif #else gnutls_global_deinit(); @@ -236,6 +256,7 @@ 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; } @@ -376,8 +397,8 @@ 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 { @@ -677,7 +698,11 @@ 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); @@ -756,11 +781,7 @@ 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)); @@ -801,14 +822,17 @@ 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; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libimobiledevice-1.2.0+git20170122.45fda81/src/idevice.h new/libimobiledevice-1.2.0+git20180427.26373b3/src/idevice.h --- old/libimobiledevice-1.2.0+git20170122.45fda81/src/idevice.h 2017-01-22 13:28:45.559033668 +0100 +++ new/libimobiledevice-1.2.0+git20180427.26373b3/src/idevice.h 2018-04-27 19:24:36.000000000 +0200 @@ -76,6 +76,7 @@ char *udid; enum connection_type conn_type; void *conn_data; + int version; }; #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libimobiledevice-1.2.0+git20170122.45fda81/src/installation_proxy.c new/libimobiledevice-1.2.0+git20180427.26373b3/src/installation_proxy.c --- old/libimobiledevice-1.2.0+git20170122.45fda81/src/installation_proxy.c 2017-01-22 13:28:45.559033668 +0100 +++ new/libimobiledevice-1.2.0+git20180427.26373b3/src/installation_proxy.c 2018-04-27 19:24:36.000000000 +0200 @@ -772,7 +772,7 @@ 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; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libimobiledevice-1.2.0+git20170122.45fda81/src/lockdown.c new/libimobiledevice-1.2.0+git20180427.26373b3/src/lockdown.c --- old/libimobiledevice-1.2.0+git20170122.45fda81/src/lockdown.c 2017-01-22 13:28:45.559033668 +0100 +++ new/libimobiledevice-1.2.0+git20180427.26373b3/src/lockdown.c 2018-04-27 19:24:36.000000000 +0200 @@ -136,6 +136,36 @@ } /** + * 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 @@ { 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 @@ 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,16 +699,28 @@ } /* 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); + 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); + } + plist_free(p_version); + } + userpref_read_pair_record(client_loc->udid, &pair_record); if (pair_record) { pair_record_get_host_id(pair_record, &host_id); @@ -712,18 +737,18 @@ 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); + } } } @@ -1113,7 +1138,6 @@ 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 +1208,14 @@ 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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libimobiledevice-1.2.0+git20170122.45fda81/src/mobileactivation.c new/libimobiledevice-1.2.0+git20180427.26373b3/src/mobileactivation.c --- old/libimobiledevice-1.2.0+git20170122.45fda81/src/mobileactivation.c 1970-01-01 01:00:00.000000000 +0100 +++ new/libimobiledevice-1.2.0+git20180427.26373b3/src/mobileactivation.c 2018-04-27 19:24:36.000000000 +0200 @@ -0,0 +1,313 @@ +/* + * mobileactivation.c + * com.apple.mobileactivationd service implementation. + * + * 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 + * 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 <string.h> +#include <stdlib.h> +#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 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; + 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; + + 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); + ret = MOBILEACTIVATION_E_REQUEST_FAILED; + free(errmsg); + } + 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) + 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_send_command_plist(client, dict, result); + plist_free(dict); + return ret; +} + +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_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) + 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_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; +} + +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_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 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; + + 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 -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libimobiledevice-1.2.0+git20170122.45fda81/src/mobileactivation.h new/libimobiledevice-1.2.0+git20180427.26373b3/src/mobileactivation.h --- old/libimobiledevice-1.2.0+git20170122.45fda81/src/mobileactivation.h 1970-01-01 01:00:00.000000000 +0100 +++ new/libimobiledevice-1.2.0+git20180427.26373b3/src/mobileactivation.h 2018-04-27 19:24:36.000000000 +0200 @@ -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 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libimobiledevice-1.2.0+git20170122.45fda81/src/property_list_service.c new/libimobiledevice-1.2.0+git20180427.26373b3/src/property_list_service.c --- old/libimobiledevice-1.2.0+git20170122.45fda81/src/property_list_service.c 2017-01-22 13:28:45.563033669 +0100 +++ new/libimobiledevice-1.2.0+git20180427.26373b3/src/property_list_service.c 2018-04-27 19:24:36.000000000 +0200 @@ -98,7 +98,8 @@ * @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 @@ } if (bytes <= 0) { debug_info("ERROR: sending to device failed."); + res = PROPERTY_LIST_SERVICE_E_MUX_ERROR; } free(content); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libimobiledevice-1.2.0+git20170122.45fda81/tools/idevicediagnostics.c new/libimobiledevice-1.2.0+git20180427.26373b3/tools/idevicediagnostics.c --- old/libimobiledevice-1.2.0+git20170122.45fda81/tools/idevicediagnostics.c 2017-01-22 13:28:45.563033669 +0100 +++ new/libimobiledevice-1.2.0+git20180427.26373b3/tools/idevicediagnostics.c 2018-04-27 19:24:36.000000000 +0200 @@ -40,7 +40,8 @@ CMD_SHUTDOWN, CMD_DIAGNOSTICS, CMD_MOBILEGESTALT, - CMD_IOREGISTRY + CMD_IOREGISTRY, + CMD_IOREGISTRY_ENTRY }; static void print_xml(plist_t node) @@ -104,7 +105,7 @@ 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; @@ -156,6 +157,15 @@ } 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 @@ 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 @@ 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"); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libimobiledevice-1.2.0+git20170122.45fda81/tools/idevicescreenshot.c new/libimobiledevice-1.2.0+git20180427.26373b3/tools/idevicescreenshot.c --- old/libimobiledevice-1.2.0+git20170122.45fda81/tools/idevicescreenshot.c 2017-01-22 13:28:45.567033669 +0100 +++ new/libimobiledevice-1.2.0+git20180427.26373b3/tools/idevicescreenshot.c 2018-04-27 19:24:36.000000000 +0200 @@ -99,12 +99,22 @@ } 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) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libimobiledevice-1.2.0+git20170122.45fda81/tools/idevicesyslog.c new/libimobiledevice-1.2.0+git20180427.26373b3/tools/idevicesyslog.c --- old/libimobiledevice-1.2.0+git20170122.45fda81/tools/idevicesyslog.c 2017-01-22 13:28:45.567033669 +0100 +++ new/libimobiledevice-1.2.0+git20180427.26373b3/tools/idevicesyslog.c 2018-04-27 19:24:36.000000000 +0200 @@ -63,9 +63,40 @@ 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);