diff options
author | Nikias Bassen | 2010-11-27 14:12:57 +0100 |
---|---|---|
committer | Martin Szulecki | 2010-11-27 15:07:18 +0100 |
commit | 70f7e3ca9e4b3dcc814ffa465bda5179f74c80e3 (patch) | |
tree | 2330080dbcdad43ca01eb7602389f491bc01fcac | |
parent | c17d3aca4fab00a11c05d8d6b537709faa4c9ff3 (diff) | |
download | libimobiledevice-70f7e3ca9e4b3dcc814ffa465bda5179f74c80e3.tar.gz libimobiledevice-70f7e3ca9e4b3dcc814ffa465bda5179f74c80e3.tar.bz2 |
Fix iOS 4.2 GnuTLS issue by passing a certificate in the handshake
-rw-r--r-- | src/idevice.c | 50 | ||||
-rw-r--r-- | src/idevice.h | 7 |
2 files changed, 54 insertions, 3 deletions
diff --git a/src/idevice.c b/src/idevice.c index c86b806..39b95c1 100644 --- a/src/idevice.c +++ b/src/idevice.c @@ -27,6 +27,7 @@ #include <usbmuxd.h> #include <gnutls/gnutls.h> #include "idevice.h" +#include "userpref.h" #include "debug.h" static idevice_event_cb_t event_cb = NULL; @@ -523,6 +524,40 @@ static void internal_ssl_cleanup(ssl_data_t ssl_data) if (ssl_data->certificate) { gnutls_certificate_free_credentials(ssl_data->certificate); } + if (ssl_data->root_cert) { + gnutls_x509_crt_deinit(ssl_data->root_cert); + } + if (ssl_data->host_cert) { + gnutls_x509_crt_deinit(ssl_data->host_cert); + } + if (ssl_data->root_privkey) { + gnutls_x509_privkey_deinit(ssl_data->root_privkey); + } + if (ssl_data->host_privkey) { + gnutls_x509_privkey_deinit(ssl_data->host_privkey); + } +} + +/** + * Internally used gnutls callback function that gets called during handshake. + */ +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) +{ + int res = -1; + gnutls_certificate_type_t type = gnutls_certificate_type_get (session); + if (type == GNUTLS_CRT_X509) { + 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"); + st->type = type; + st->ncerts = 1; + st->cert.x509 = &ssl_data->host_cert; + st->key.x509 = ssl_data->host_privkey; + st->deinit_all = 0; + res = 0; + } + } + return res; } /** @@ -549,7 +584,7 @@ idevice_error_t idevice_connection_enable_ssl(idevice_connection_t connection) errno = 0; gnutls_global_init(); gnutls_certificate_allocate_credentials(&ssl_data_loc->certificate); - gnutls_certificate_set_x509_trust_file(ssl_data_loc->certificate, "hostcert.pem", GNUTLS_X509_FMT_PEM); + gnutls_certificate_client_set_retrieve_function (ssl_data_loc->certificate, internal_cert_callback); gnutls_init(&ssl_data_loc->session, GNUTLS_CLIENT); { int protocol_priority[16] = { GNUTLS_SSL3, 0 }; @@ -564,7 +599,18 @@ idevice_error_t idevice_connection_enable_ssl(idevice_connection_t connection) gnutls_protocol_set_priority(ssl_data_loc->session, protocol_priority); gnutls_mac_set_priority(ssl_data_loc->session, mac_priority); } - gnutls_credentials_set(ssl_data_loc->session, GNUTLS_CRD_CERTIFICATE, ssl_data_loc->certificate); /* this part is killing me. */ + 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); + + gnutls_x509_crt_init(&ssl_data_loc->root_cert); + gnutls_x509_crt_init(&ssl_data_loc->host_cert); + gnutls_x509_privkey_init(&ssl_data_loc->root_privkey); + gnutls_x509_privkey_init(&ssl_data_loc->host_privkey); + + userpref_error_t uerr = userpref_get_keys_and_certs(ssl_data_loc->root_privkey, ssl_data_loc->root_cert, ssl_data_loc->host_privkey, ssl_data_loc->host_cert); + if (uerr != USERPREF_E_SUCCESS) { + debug_info("Error %d when loading keys and certificates! %d", uerr); + } debug_info("GnuTLS step 1..."); gnutls_transport_set_ptr(ssl_data_loc->session, (gnutls_transport_ptr_t)connection); diff --git a/src/idevice.h b/src/idevice.h index a4ce251..231b3ab 100644 --- a/src/idevice.h +++ b/src/idevice.h @@ -22,6 +22,7 @@ #define IDEVICE_H #include <gnutls/gnutls.h> +#include <gnutls/x509.h> #include "libimobiledevice/libimobiledevice.h" @@ -30,8 +31,12 @@ enum connection_type { }; struct ssl_data_private { - gnutls_certificate_credentials_t certificate; + gnutls_certificate_credentials_t certificate; gnutls_session_t session; + gnutls_x509_privkey_t root_privkey; + gnutls_x509_crt_t root_cert; + gnutls_x509_privkey_t host_privkey; + gnutls_x509_crt_t host_cert; }; typedef struct ssl_data_private *ssl_data_t; |