Control: tags 840931 + pending Dear maintainer,
I've prepared an NMU for libimobiledevice (versioned as 1.2.0+dfsg-3.1) and uploaded it to DELAYED/2. Please feel free to tell me if I should delay it longer. Regards.
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; + }