diff --git a/configure.ac b/configure.ac index 150c2d80..9fcc287b 100644 --- a/configure.ac +++ b/configure.ac @@ -18,7 +18,8 @@ PKG_PROG_PKG_CONFIG # Checks for libraries. PKG_CHECK_MODULES(libimobiledevice, libimobiledevice-1.0 >= 1.3.0) PKG_CHECK_MODULES(libplist, libplist-2.0 >= 2.2.0) -PKG_CHECK_MODULES(openssl, openssl >= 0.9.8) +PKG_CHECK_MODULES(libusbmuxd, libusbmuxd-2.0 >= 2.0.0) +PKG_CHECK_MODULES(openssl, openssl >= 1.1.0) AC_CHECK_LIB([plist-2.0], [plist_to_xml], [ ], [AC_MSG_FAILURE([*** Unable to link with libplist])], [$libplist_LIBS]) diff --git a/examples/Makefile.am b/examples/Makefile.am index 2a2f9a12..fe25fb31 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -3,8 +3,8 @@ AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/src -AM_CFLAGS = $(GLOBAL_CFLAGS) $(libimobiledevice_CFLAGS) $(libplist_CFLAGS) $(openssl_CFLAGS) -AM_LDFLAGS = $(libimobiledevice_LIBS) $(libplist_LIBS) $(openssl_LIBS) +AM_CFLAGS = $(GLOBAL_CFLAGS) $(libimobiledevice_CFLAGS) $(libplist_CFLAGS) $(libusbmuxd_CFLAGS) $(openssl_CFLAGS) +AM_LDFLAGS = $(libimobiledevice_LIBS) $(libplist_LIBS) $(libusbmuxd_LIBS) $(openssl_LIBS) noinst_PROGRAMS = ws_echo1 ws_echo2 wi_client dl_client @@ -34,10 +34,12 @@ wi_client_SOURCES = \ wi_client.c \ char_buffer.h \ rpc.h \ + idevice_ext.h \ webinspector.h wi_client_LDADD = \ ../src/char_buffer.o \ ../src/rpc.o \ + ../src/idevice_ext.o \ ../src/webinspector.o dl_client_SOURCES = \ diff --git a/include/ios-webkit-debug-proxy/idevice_ext.h b/include/ios-webkit-debug-proxy/idevice_ext.h new file mode 100644 index 00000000..cf07fb78 --- /dev/null +++ b/include/ios-webkit-debug-proxy/idevice_ext.h @@ -0,0 +1,24 @@ +// Google BSD license https://developers.google.com/google-bsd-license +// Copyright 2012 Google Inc. wrightt@google.com + +// +// libimobildevice extensions +// + +#ifndef IDEVICE_EXT_H +#define IDEVICE_EXT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +int idevice_ext_connection_enable_ssl(const char *device_id, int fd, SSL **to_session); + +#ifdef __cplusplus +} +#endif + +#endif /* IDEVICE_EXT_H */ diff --git a/src/Makefile.am b/src/Makefile.am index a16c481f..c7c5e34f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -3,8 +3,8 @@ AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/include/ios-webkit-debug-proxy -AM_CFLAGS = $(GLOBAL_CFLAGS) $(libimobiledevice_CFLAGS) $(libplist_CFLAGS) $(libpcreposix_CFLAGS) $(openssl_CFLAGS) -AM_LDFLAGS = $(libimobiledevice_LIBS) $(libplist_LIBS) $(libpcreposix_LIBS) $(openssl_LIBS) +AM_CFLAGS = $(GLOBAL_CFLAGS) $(libimobiledevice_CFLAGS) $(libplist_CFLAGS) $(libusbmuxd_CFLAGS) $(libpcreposix_CFLAGS) $(openssl_CFLAGS) +AM_LDFLAGS = $(libimobiledevice_LIBS) $(libplist_LIBS) $(libusbmuxd_LIBS) $(libpcreposix_LIBS) $(openssl_LIBS) lib_LTLIBRARIES = libios_webkit_debug_proxy.la libios_webkit_debug_proxy_la_LIBADD = @@ -20,6 +20,7 @@ libios_webkit_debug_proxy_la_SOURCES = ios_webkit_debug_proxy_main.c \ sha1.c sha1.h \ socket_manager.c socket_manager.h \ validate_utf8.h \ + idevice_ext.c idevice_ext.h \ webinspector.c webinspector.h \ websocket.c websocket.h @@ -35,6 +36,7 @@ ios_webkit_debug_proxy_SOURCES = ios_webkit_debug_proxy_main.c \ sha1.c sha1.h \ socket_manager.c socket_manager.h \ validate_utf8.h \ + idevice_ext.c idevice_ext.h \ webinspector.c webinspector.h \ websocket.c websocket.h ios_webkit_debug_proxy_CFLAGS = $(AM_CFLAGS) diff --git a/src/idevice_ext.c b/src/idevice_ext.c new file mode 100644 index 00000000..4e6736c2 --- /dev/null +++ b/src/idevice_ext.c @@ -0,0 +1,144 @@ +// Google BSD license https://developers.google.com/google-bsd-license +// Copyright 2012 Google Inc. wrightt@google.com + +#ifdef HAVE_CONFIG_H +#include +#endif + +#define _GNU_SOURCE +#include +#include +#include +#ifdef WIN32 +#include +#endif + +#include + +#include "idevice_ext.h" + +typedef struct { + unsigned char *data; + unsigned int size; +} key_data_t; + +int read_pair_record(const char *udid, plist_t *pair_record) { + char* record_data = NULL; + uint32_t record_size = 0; + + int res = usbmuxd_read_pair_record(udid, &record_data, &record_size); + if (res < 0) { + free(record_data); + return -1; + } + + *pair_record = NULL; + plist_from_memory(record_data, record_size, pair_record); + free(record_data); + + if (!*pair_record) { + return -1; + } + + return 0; +} + +int pair_record_get_item_as_key_data(plist_t pair_record, const char* name, key_data_t *value) { + char* buffer = NULL; + uint64_t length = 0; + plist_t node = plist_dict_get_item(pair_record, name); + + if (node && plist_get_node_type(node) == PLIST_DATA) { + plist_get_data_val(node, &buffer, &length); + value->data = (unsigned char*)malloc(length+1); + memcpy(value->data, buffer, length); + value->data[length] = '\0'; + value->size = length+1; + free(buffer); + return 0; + } + + return -1; +} + +int idevice_ext_connection_enable_ssl(const char *device_id, int fd, SSL **to_session) { + plist_t pair_record = NULL; + if (read_pair_record(device_id, &pair_record)) { + fprintf(stderr, "Failed to read pair record\n"); + return -1; + } + + key_data_t root_cert = { NULL, 0 }; + key_data_t root_privkey = { NULL, 0 }; + pair_record_get_item_as_key_data(pair_record, "RootCertificate", &root_cert); + pair_record_get_item_as_key_data(pair_record, "RootPrivateKey", &root_privkey); + plist_free(pair_record); + + BIO *ssl_bio = BIO_new(BIO_s_socket()); + if (!ssl_bio) { + fprintf(stderr, "Could not create SSL bio\n"); + return -1; + } + + BIO_set_fd(ssl_bio, fd, BIO_NOCLOSE); + SSL_CTX *ssl_ctx = SSL_CTX_new(TLS_method()); + if (ssl_ctx == NULL) { + fprintf(stderr, "Could not create SSL context\n"); + BIO_free(ssl_bio); + } + + SSL_CTX_set_security_level(ssl_ctx, 0); + SSL_CTX_set_min_proto_version(ssl_ctx, TLS1_VERSION); + + BIO* membp; + X509* rootCert = NULL; + membp = BIO_new_mem_buf(root_cert.data, root_cert.size); + PEM_read_bio_X509(membp, &rootCert, NULL, NULL); + BIO_free(membp); + SSL_CTX_use_certificate(ssl_ctx, rootCert); + X509_free(rootCert); + free(root_cert.data); + + RSA* rootPrivKey = NULL; + membp = BIO_new_mem_buf(root_privkey.data, root_privkey.size); + PEM_read_bio_RSAPrivateKey(membp, &rootPrivKey, NULL, NULL); + BIO_free(membp); + SSL_CTX_use_RSAPrivateKey(ssl_ctx, rootPrivKey); + RSA_free(rootPrivKey); + free(root_privkey.data); + + SSL *ssl = SSL_new(ssl_ctx); + if (!ssl) { + fprintf(stderr, "Could not create SSL object\n"); + BIO_free(ssl_bio); + SSL_CTX_free(ssl_ctx); + return -1; + } + + SSL_set_connect_state(ssl); + SSL_set_verify(ssl, 0, NULL); + SSL_set_bio(ssl, ssl_bio, ssl_bio); + + int ssl_error = 0; + while (1) { + ssl_error = SSL_get_error(ssl, SSL_do_handshake(ssl)); + if (ssl_error == 0 || ssl_error != SSL_ERROR_WANT_READ) { + break; + } +#ifdef WIN32 + Sleep(100); +#else + struct timespec ts = { 0, 100000000 }; + nanosleep(&ts, NULL); +#endif + } + + if (ssl_error != 0) { + SSL_free(ssl); + SSL_CTX_free(ssl_ctx); + return ssl_error; + } + + *to_session = ssl; + return 0; +} diff --git a/src/socket_manager.c b/src/socket_manager.c index 6946f5f4..954ddeb1 100644 --- a/src/socket_manager.c +++ b/src/socket_manager.c @@ -340,7 +340,11 @@ sm_status sm_remove_fd(sm_t self, int fd) { if (!FD_ISSET(fd, my->all_fds)) { return SM_ERROR; } - ht_put(my->fd_to_ssl, HT_KEY(fd), NULL); + SSL *ssl_session = (SSL *)ht_put(my->fd_to_ssl, HT_KEY(fd), NULL); + if (ssl_session) { + SSL_shutdown(ssl_session); + SSL_free(ssl_session); + } void *value = ht_put(my->fd_to_value, HT_KEY(fd), NULL); bool is_server = FD_ISSET(fd, my->server_fds); sm_on_debug(self, "ss.remove%s_fd(%d)", (is_server ? "_server" : ""), fd); diff --git a/src/webinspector.c b/src/webinspector.c index f74d5d9b..1570a458 100644 --- a/src/webinspector.c +++ b/src/webinspector.c @@ -30,6 +30,7 @@ #include #include "char_buffer.h" +#include "idevice_ext.h" #include "webinspector.h" @@ -52,50 +53,6 @@ struct wi_private { // // CONNECT // - -// based on latest libimobiledevice/src/idevice.h -struct idevice_connection_private { - idevice_t device; - enum idevice_connection_type type; - void *data; - void *ssl_data; -}; - -struct ssl_data_private { - SSL *session; - SSL_CTX *ctx; -}; -typedef struct ssl_data_private *ssl_data_t; - -wi_status idevice_connection_get_ssl_session(idevice_connection_t connection, - SSL **to_session) { - if (!connection || !to_session) { - return WI_ERROR; - } - - idevice_connection_private *c = ( - (sizeof(*connection) == sizeof(idevice_connection_private)) ? - (idevice_connection_private *) connection : NULL); - - if (!c || c->data <= 0) { - perror("Invalid idevice_connection struct. Please verify that " - __FILE__ "'s idevice_connection_private matches your version of" - " libimbiledevice/src/idevice.h"); - return WI_ERROR; - } - - ssl_data_t sd = (ssl_data_t)c->ssl_data; - if (!sd || !sd->session) { - perror("Invalid ssl_data struct. Make sure libimobiledevice was compiled" - " with openssl. Otherwise please verify that " __FILE__ "'s ssl_data" - " matches your version of libimbiledevice/src/idevice.h"); - return WI_ERROR; - } - - *to_session = sd->session; - return WI_SUCCESS; -} - int wi_connect(const char *device_id, char **to_device_id, char **to_device_name, int *to_device_os_version, void **to_ssl_session, int recv_timeout) { @@ -166,16 +123,6 @@ int wi_connect(const char *device_id, char **to_device_id, goto leave_cleanup; } - // enable ssl - if (service->ssl_enabled == 1) { - if (!to_ssl_session || idevice_connection_enable_ssl(connection) || - idevice_connection_get_ssl_session(connection, &ssl_session)) { - perror("ssl connection failed!"); - goto leave_cleanup; - } - *to_ssl_session = ssl_session; - } - if (client) { // not needed anymore lockdownd_client_free(client); @@ -188,6 +135,16 @@ int wi_connect(const char *device_id, char **to_device_id, goto leave_cleanup; } + // enable ssl + if (service->ssl_enabled == 1) { + int ssl_ret = 0; + if (!to_ssl_session || (ssl_ret = idevice_ext_connection_enable_ssl(device_id, fd, &ssl_session))) { + fprintf(stderr, "SSL connection failed! Error code: %d\n", ssl_ret); + goto leave_cleanup; + } + *to_ssl_session = ssl_session; + } + if (recv_timeout < 0) { #ifdef WIN32 u_long nb = 1;