summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2010-11-27 14:12:57 +0100
committerGravatar Nikias Bassen2010-11-27 14:12:57 +0100
commit363098c083a8cd7acc6ca902c92ecdae0f3ef2fb (patch)
treec22775263249ba165cf3193314ed8649d17f0487
parent139306caebdcc9e4383795227ca3662d484e04d5 (diff)
downloadlibimobiledevice-363098c083a8cd7acc6ca902c92ecdae0f3ef2fb.tar.gz
libimobiledevice-363098c083a8cd7acc6ca902c92ecdae0f3ef2fb.tar.bz2
Fix iOS 4.2 GnuTLS issue by passing a certificate in the handshake
-rw-r--r--src/idevice.c50
-rw-r--r--src/idevice.h7
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 @@
27#include <usbmuxd.h> 27#include <usbmuxd.h>
28#include <gnutls/gnutls.h> 28#include <gnutls/gnutls.h>
29#include "idevice.h" 29#include "idevice.h"
30#include "userpref.h"
30#include "debug.h" 31#include "debug.h"
31 32
32static idevice_event_cb_t event_cb = NULL; 33static idevice_event_cb_t event_cb = NULL;
@@ -523,6 +524,40 @@ static void internal_ssl_cleanup(ssl_data_t ssl_data)
523 if (ssl_data->certificate) { 524 if (ssl_data->certificate) {
524 gnutls_certificate_free_credentials(ssl_data->certificate); 525 gnutls_certificate_free_credentials(ssl_data->certificate);
525 } 526 }
527 if (ssl_data->root_cert) {
528 gnutls_x509_crt_deinit(ssl_data->root_cert);
529 }
530 if (ssl_data->host_cert) {
531 gnutls_x509_crt_deinit(ssl_data->host_cert);
532 }
533 if (ssl_data->root_privkey) {
534 gnutls_x509_privkey_deinit(ssl_data->root_privkey);
535 }
536 if (ssl_data->host_privkey) {
537 gnutls_x509_privkey_deinit(ssl_data->host_privkey);
538 }
539}
540
541/**
542 * Internally used gnutls callback function that gets called during handshake.
543 */
544static 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)
545{
546 int res = -1;
547 gnutls_certificate_type_t type = gnutls_certificate_type_get (session);
548 if (type == GNUTLS_CRT_X509) {
549 ssl_data_t ssl_data = (ssl_data_t)gnutls_session_get_ptr (session);
550 if (ssl_data && ssl_data->host_privkey && ssl_data->host_cert) {
551 debug_info("Passing certificate");
552 st->type = type;
553 st->ncerts = 1;
554 st->cert.x509 = &ssl_data->host_cert;
555 st->key.x509 = ssl_data->host_privkey;
556 st->deinit_all = 0;
557 res = 0;
558 }
559 }
560 return res;
526} 561}
527 562
528/** 563/**
@@ -549,7 +584,7 @@ idevice_error_t idevice_connection_enable_ssl(idevice_connection_t connection)
549 errno = 0; 584 errno = 0;
550 gnutls_global_init(); 585 gnutls_global_init();
551 gnutls_certificate_allocate_credentials(&ssl_data_loc->certificate); 586 gnutls_certificate_allocate_credentials(&ssl_data_loc->certificate);
552 gnutls_certificate_set_x509_trust_file(ssl_data_loc->certificate, "hostcert.pem", GNUTLS_X509_FMT_PEM); 587 gnutls_certificate_client_set_retrieve_function (ssl_data_loc->certificate, internal_cert_callback);
553 gnutls_init(&ssl_data_loc->session, GNUTLS_CLIENT); 588 gnutls_init(&ssl_data_loc->session, GNUTLS_CLIENT);
554 { 589 {
555 int protocol_priority[16] = { GNUTLS_SSL3, 0 }; 590 int protocol_priority[16] = { GNUTLS_SSL3, 0 };
@@ -564,7 +599,18 @@ idevice_error_t idevice_connection_enable_ssl(idevice_connection_t connection)
564 gnutls_protocol_set_priority(ssl_data_loc->session, protocol_priority); 599 gnutls_protocol_set_priority(ssl_data_loc->session, protocol_priority);
565 gnutls_mac_set_priority(ssl_data_loc->session, mac_priority); 600 gnutls_mac_set_priority(ssl_data_loc->session, mac_priority);
566 } 601 }
567 gnutls_credentials_set(ssl_data_loc->session, GNUTLS_CRD_CERTIFICATE, ssl_data_loc->certificate); /* this part is killing me. */ 602 gnutls_credentials_set(ssl_data_loc->session, GNUTLS_CRD_CERTIFICATE, ssl_data_loc->certificate);
603 gnutls_session_set_ptr(ssl_data_loc->session, ssl_data_loc);
604
605 gnutls_x509_crt_init(&ssl_data_loc->root_cert);
606 gnutls_x509_crt_init(&ssl_data_loc->host_cert);
607 gnutls_x509_privkey_init(&ssl_data_loc->root_privkey);
608 gnutls_x509_privkey_init(&ssl_data_loc->host_privkey);
609
610 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);
611 if (uerr != USERPREF_E_SUCCESS) {
612 debug_info("Error %d when loading keys and certificates! %d", uerr);
613 }
568 614
569 debug_info("GnuTLS step 1..."); 615 debug_info("GnuTLS step 1...");
570 gnutls_transport_set_ptr(ssl_data_loc->session, (gnutls_transport_ptr_t)connection); 616 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 @@
22#define IDEVICE_H 22#define IDEVICE_H
23 23
24#include <gnutls/gnutls.h> 24#include <gnutls/gnutls.h>
25#include <gnutls/x509.h>
25 26
26#include "libimobiledevice/libimobiledevice.h" 27#include "libimobiledevice/libimobiledevice.h"
27 28
@@ -30,8 +31,12 @@ enum connection_type {
30}; 31};
31 32
32struct ssl_data_private { 33struct ssl_data_private {
33 gnutls_certificate_credentials_t certificate; 34 gnutls_certificate_credentials_t certificate;
34 gnutls_session_t session; 35 gnutls_session_t session;
36 gnutls_x509_privkey_t root_privkey;
37 gnutls_x509_crt_t root_cert;
38 gnutls_x509_privkey_t host_privkey;
39 gnutls_x509_crt_t host_cert;
35}; 40};
36typedef struct ssl_data_private *ssl_data_t; 41typedef struct ssl_data_private *ssl_data_t;
37 42