Package: libimobiledevice4
Followup-For: Bug #840931
Control: reassign 840931 libimobiledevice6 1.2.0+dfsg-3
Control: affects 840931 ifuse
Control: merge 840931 847977
Control: tags 840931 patch

Hello.

The attached diff applies the two upstream commits described above, as
well as another one described at the end of
https://github.com/libimobiledevice/libimobiledevice/issues/413.

All three patches are required to connect an iOS 4.5.1.
diff -Nru libimobiledevice-1.2.0+dfsg/debian/changelog libimobiledevice-1.2.0+dfsg/debian/changelog
--- libimobiledevice-1.2.0+dfsg/debian/changelog	2016-06-02 18:55:15.000000000 +0200
+++ libimobiledevice-1.2.0+dfsg/debian/changelog	2017-01-03 01:32:36.000000000 +0100
@@ -1,3 +1,12 @@
+libimobiledevice (1.2.0+dfsg-3.1) unstable; urgency=medium
+
+  * Non-maintainer upload.
+  * Upstream commits replacing SSL3.0 with TLS1.0. Closes: #840931, #847977.
+    Also fix related bug in GNUTLS pairing record generation, see
+    https://github.com/libimobiledevice/libimobiledevice/issues/413.
+
+ -- Nicolas Boulenguez <nico...@debian.org>  Tue, 03 Jan 2017 01:32:36 +0100
+
 libimobiledevice (1.2.0+dfsg-3) unstable; urgency=high
 
   * Team upload
diff -Nru libimobiledevice-1.2.0+dfsg/debian/patches/fix-ssl-version-negotiation-for-newer-versions-of-openssl.diff libimobiledevice-1.2.0+dfsg/debian/patches/fix-ssl-version-negotiation-for-newer-versions-of-openssl.diff
--- libimobiledevice-1.2.0+dfsg/debian/patches/fix-ssl-version-negotiation-for-newer-versions-of-openssl.diff	1970-01-01 01:00:00.000000000 +0100
+++ libimobiledevice-1.2.0+dfsg/debian/patches/fix-ssl-version-negotiation-for-newer-versions-of-openssl.diff	2017-01-03 01:32:36.000000000 +0100
@@ -0,0 +1,20 @@
+Description: 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...
+Origin: upstream, https://cgit.libimobiledevice.org/libimobiledevice.git/commit/?id=13bf235cac2201747de11652cf14fe2714ca0718
+Author: David Weinstein
+Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=840931
+Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=847977
+
+--- a/src/idevice.c
++++ b/src/idevice.c
+@@ -687,7 +687,7 @@
+ 	}
+ 	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);
diff -Nru libimobiledevice-1.2.0+dfsg/debian/patches/idevice-update-gnutls-code-to-support-ios-10.diff libimobiledevice-1.2.0+dfsg/debian/patches/idevice-update-gnutls-code-to-support-ios-10.diff
--- libimobiledevice-1.2.0+dfsg/debian/patches/idevice-update-gnutls-code-to-support-ios-10.diff	1970-01-01 01:00:00.000000000 +0100
+++ libimobiledevice-1.2.0+dfsg/debian/patches/idevice-update-gnutls-code-to-support-ios-10.diff	2017-01-03 01:32:36.000000000 +0100
@@ -0,0 +1,21 @@
+Description: 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.
+Origin: upstream, https://cgit.libimobiledevice.org/libimobiledevice.git/commit/?id=72643b2b83990b9cf97cc84b285b30763d44a72d
+Author: Jay Freeman (saurik)
+Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=840931
+Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=847977
+
+--- a/src/idevice.c
++++ b/src/idevice.c
+@@ -758,7 +758,7 @@
+ 	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);
+ 
diff -Nru libimobiledevice-1.2.0+dfsg/debian/patches/series libimobiledevice-1.2.0+dfsg/debian/patches/series
--- libimobiledevice-1.2.0+dfsg/debian/patches/series	2016-06-02 18:55:15.000000000 +0200
+++ libimobiledevice-1.2.0+dfsg/debian/patches/series	2017-01-03 01:32:36.000000000 +0100
@@ -2,3 +2,6 @@
 09_use_python_config.patch
 local-only-sockets.patch
 gnutls-api-update.patch
+fix-ssl-version-negotiation-for-newer-versions-of-openssl.diff
+idevice-update-gnutls-code-to-support-ios-10.diff
+userpref-gnutls-fix-pairing-record-generation-and-improve-error-handling.diff
diff -Nru libimobiledevice-1.2.0+dfsg/debian/patches/userpref-gnutls-fix-pairing-record-generation-and-improve-error-handling.diff libimobiledevice-1.2.0+dfsg/debian/patches/userpref-gnutls-fix-pairing-record-generation-and-improve-error-handling.diff
--- libimobiledevice-1.2.0+dfsg/debian/patches/userpref-gnutls-fix-pairing-record-generation-and-improve-error-handling.diff	1970-01-01 01:00:00.000000000 +0100
+++ libimobiledevice-1.2.0+dfsg/debian/patches/userpref-gnutls-fix-pairing-record-generation-and-improve-error-handling.diff	2017-01-03 01:32:36.000000000 +0100
@@ -0,0 +1,164 @@
+Description: 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.
+Origin: upstream, https://github.com/libimobiledevice/libimobiledevice/commit/23069d10341ce637fdad7321d447c53752dba48c
+Author: Nikias Bassen
+Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=840931
+Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=847977
+
+--- a/common/userpref.c
++++ b/common/userpref.c
+@@ -672,15 +672,13 @@
+ 	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)) {
+@@ -699,8 +697,14 @@
+ 
+ 				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);
+@@ -708,12 +712,15 @@
+ 		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;
+@@ -721,8 +728,9 @@
+ 		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);
+@@ -741,9 +749,8 @@
+ 			}
+ 
+ 			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);
+@@ -751,13 +758,11 @@
+ 				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);
+ 	}
+@@ -772,27 +777,27 @@
+ 
+ 	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;
+ }

Reply via email to