diff --git a/README b/README index 5bc5c5e..a8366d4 100644 --- a/README +++ b/README @@ -10,7 +10,7 @@ You must have: libusb-dev libfuse-dev (and the associated kernel modules) libglib2.0-dev - libxml2-dev + libplist (git clone git://github.com/JonathanBeck/libplist.git) make autoheader automake diff --git a/configure.ac b/configure.ac index 2cabe29..82ed1e9 100644 --- a/configure.ac +++ b/configure.ac @@ -14,7 +14,7 @@ AC_PROG_CC AM_PROG_CC_C_O # Checks for libraries. -PKG_CHECK_MODULES(libxml2, libxml-2.0 >= 2.6.30) +PKG_CHECK_MODULES(libplist, libplist >= 0.1.0) PKG_CHECK_MODULES(libusb, libusb >= 0.1.12) PKG_CHECK_MODULES(libglib2, glib-2.0 >= 2.14.1) PKG_CHECK_MODULES(libgthread2, gthread-2.0 >= 2.14.1) diff --git a/dev/Makefile.am b/dev/Makefile.am index 5f85ad7..c04662e 100644 --- a/dev/Makefile.am +++ b/dev/Makefile.am @@ -1,7 +1,7 @@ INCLUDES = -I$(top_srcdir)/include -AM_CFLAGS = $(libxml2_CFLAGS) $(libusb_CFLAGS) $(libglib2_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(libgthread2_CFLAGS) -g $(LFS_CFLAGS) -AM_LDFLAGS = $(libxml2_LIBS) $(libusb_LIBS) $(libglib2_LIBS) $(libgnutls_LIBS) $(libtasn1_LIBS) $(libgthread2_LIBS) +AM_CFLAGS = $(libplist_CFLAGS) $(libusb_CFLAGS) $(libglib2_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(libgthread2_CFLAGS) -g $(LFS_CFLAGS) +AM_LDFLAGS = $(libplist_LIBS) $(libusb_LIBS) $(libglib2_LIBS) $(libgnutls_LIBS) $(libtasn1_LIBS) $(libgthread2_LIBS) bin_PROGRAMS = iphoneclient lckd-client afccheck diff --git a/dev/main.c b/dev/main.c index c68427b..52eedb3 100644 --- a/dev/main.c +++ b/dev/main.c @@ -24,9 +24,6 @@ #include #include -#include -#include - #include void perform_syncWillStart(iphone_device_t phone, iphone_lckd_client_t control) diff --git a/libiphone-1.0.pc.in b/libiphone-1.0.pc.in index c496464..269ebf5 100644 --- a/libiphone-1.0.pc.in +++ b/libiphone-1.0.pc.in @@ -6,7 +6,7 @@ includedir=@includedir@ Name: libiphone Description: A library to communicate with the Lockdown server on the iPhone Version: @VERSION@ -Requires: libxml-2.0 >= 2.6.30 libusb >= 0.1.12 glib-2.0 >= 2.14.1 gthread-2.0 >= 2.14.1 gnutls >= 1.6.3 libtasn1 >= 1.1 +Requires: libplist >= 0.1.0 libusb >= 0.1.12 glib-2.0 >= 2.14.1 gthread-2.0 >= 2.14.1 gnutls >= 1.6.3 libtasn1 >= 1.1 Libs: -L${libdir} -liphone Cflags: -I${includedir} diff --git a/src/AFC.c b/src/AFC.c index af07b56..480f99e 100644 --- a/src/AFC.c +++ b/src/AFC.c @@ -21,8 +21,6 @@ #include #include "AFC.h" -#include "plist.h" -#include "utils.h" // This is the maximum size an AFC data packet can be diff --git a/src/Makefile.am b/src/Makefile.am index 76b15ec..1a41079 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,15 +1,15 @@ INCLUDES = -I$(top_srcdir)/include -AM_CFLAGS = $(libxml2_CFLAGS) $(libusb_CFLAGS) $(libglib2_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(libgthread2_CFLAGS) -g -Wall $(LFS_CFLAGS) -AM_LDFLAGS = $(libxml2_LIBS) $(libusb_LIBS) $(libglib2_LIBS) $(libgnutls_LIBS) $(libtasn1_LIBS) $(libgthread2_LIBS) +AM_CFLAGS = $(libplist_CFLAGS) $(libusb_CFLAGS) $(libglib2_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(libgthread2_CFLAGS) -g -Wall $(LFS_CFLAGS) +AM_LDFLAGS = $(libplist_LIBS) $(libusb_LIBS) $(libglib2_LIBS) $(libgnutls_LIBS) $(libtasn1_LIBS) $(libgthread2_LIBS) bin_PROGRAMS = libiphone-initconf -libiphone_initconf_SOURCES = initconf.c userpref.c lockdown.c plist.c usbmux.c iphone.c utils.c +libiphone_initconf_SOURCES = initconf.c userpref.c lockdown.c usbmux.c iphone.c utils.c libiphone_initconf_CFLAGS = $(libgthread2_CFLAGS) $(AM_CFLAGS) libiphone_initconf_LDFLAGS = $(libgthread2_LIBS) $(AM_LDFLAGS) lib_LTLIBRARIES = libiphone.la -libiphone_la_SOURCES = usbmux.c iphone.c plist.c lockdown.c AFC.c NotificationProxy.c userpref.c utils.c +libiphone_la_SOURCES = usbmux.c iphone.c lockdown.c AFC.c NotificationProxy.c userpref.c utils.c diff --git a/src/NotificationProxy.c b/src/NotificationProxy.c index c13a547..a99b9f6 100644 --- a/src/NotificationProxy.c +++ b/src/NotificationProxy.c @@ -20,8 +20,10 @@ */ #include +#include +#include +#include #include "NotificationProxy.h" -#include "plist.h" #include "utils.h" /** Locks an NP client, done for thread safety stuff. @@ -103,13 +105,11 @@ iphone_error_t iphone_np_free_client(iphone_np_client_t client) */ iphone_error_t iphone_np_post_notification(iphone_np_client_t client, const char *notification) { - xmlDocPtr plist; - xmlNode *dict, *key; - char *XML_content; - uint32_t length; + plist_t dict = NULL; + char *XML_content = NULL; + uint32_t length = 0; int bytes; - iphone_error_t ret; - unsigned char sndbuf[4096]; + char sndbuf[4096]; int sndlen = 0; int nlen; @@ -118,49 +118,49 @@ iphone_error_t iphone_np_post_notification(iphone_np_client_t client, const char } np_lock(client); - plist = new_plist(); - dict = add_child_to_plist(plist, "dict", "\n", NULL, 0); - key = add_key_str_dict_element(plist, dict, "Command", "PostNotification", 1); - key = add_key_str_dict_element(plist, dict, "Name", notification, 1); - xmlDocDumpMemory(plist, (xmlChar **) & XML_content, &length); + dict = plist_new_dict(); + plist_add_sub_key_el(dict, "Command"); + plist_add_sub_string_el(dict, "PostNotification"); + plist_add_sub_key_el(dict, "Name"); + plist_add_sub_string_el(dict, notification); + plist_to_xml(dict, &XML_content, &length); nlen = htonl(length); - memcpy(sndbuf + sndlen, &nlen, 4); sndlen += 4; memcpy(sndbuf + sndlen, XML_content, length); sndlen += length; - xmlFree(XML_content); - xmlFreeDoc(plist); + free(XML_content); + XML_content = NULL; + plist_free(dict); - plist = new_plist(); - dict = add_child_to_plist(plist, "dict", "\n", NULL, 0); - key = add_key_str_dict_element(plist, dict, "Command", "Shutdown", 1); - xmlDocDumpMemory(plist, (xmlChar **) & XML_content, &length); + dict = plist_new_dict(); + plist_add_sub_key_el(dict, "Command"); + plist_add_sub_string_el(dict, "Shutdown"); + plist_to_xml(dict, &XML_content, &length); nlen = htonl(length); - memcpy(sndbuf + sndlen, &nlen, 4); sndlen += 4; - memcpy(sndbuf + sndlen, XML_content, length); sndlen += length; - xmlFree(XML_content); - xmlFreeDoc(plist); - plist = NULL; + free(XML_content); + XML_content = NULL; + plist_free(dict); + dict = NULL; log_debug_buffer(sndbuf, sndlen); - iphone_mux_send(client->connection, sndbuf, sndlen, &bytes); + iphone_mux_send(client->connection, sndbuf, sndlen, (uint32_t*)&bytes); if (bytes <= 0) { np_unlock(client); return bytes; } np_unlock(client); - return bytes; + return IPHONE_E_SUCCESS; } /** Notifies the iphone to send a notification on certain events. @@ -180,13 +180,11 @@ iphone_error_t iphone_np_post_notification(iphone_np_client_t client, const char */ iphone_error_t iphone_np_observe_notification(iphone_np_client_t client) { - xmlDocPtr plist; - xmlNode *dict, *key; + plist_t dict; char *XML_content; uint32_t length; int bytes; - iphone_error_t ret; - unsigned char sndbuf[4096]; + char sndbuf[4096]; int sndlen = 0; int nlen; int i = 0; @@ -211,11 +209,12 @@ iphone_error_t iphone_np_observe_notification(iphone_np_client_t client) np_lock(client); while (notifications[i]) { - plist = new_plist(); - dict = add_child_to_plist(plist, "dict", "\n", NULL, 0); - key = add_key_str_dict_element(plist, dict, "Command", "ObserveNotification", 1); - key = add_key_str_dict_element(plist, dict, "Name", notifications[i++], 1); - xmlDocDumpMemory(plist, (xmlChar **) & XML_content, &length); + dict = plist_new_dict(); + plist_add_sub_key_el(dict, "Command"); + plist_add_sub_string_el(dict, "ObserveNotification"); + plist_add_sub_key_el(dict, "Name"); + plist_add_sub_string_el(dict, notifications[i]); + plist_to_xml(dict, &XML_content, &length); nlen = htonl(length); memcpy(sndbuf + sndlen, &nlen, 4); @@ -223,35 +222,37 @@ iphone_error_t iphone_np_observe_notification(iphone_np_client_t client) memcpy(sndbuf + sndlen, XML_content, length); sndlen += length; - xmlFree(XML_content); - xmlFreeDoc(plist); + free(XML_content); + XML_content = NULL; + plist_free(dict); + + i++; } - plist = new_plist(); - dict = add_child_to_plist(plist, "dict", "\n", NULL, 0); - key = add_key_str_dict_element(plist, dict, "Command", "Shutdown", 1); - xmlDocDumpMemory(plist, (xmlChar **) & XML_content, &length); + dict = plist_new_dict(); + plist_add_sub_key_el(dict, "Command"); + plist_add_sub_string_el(dict, "Shutdown"); + plist_to_xml(dict, &XML_content, &length); nlen = htonl(length); - memcpy(sndbuf + sndlen, &nlen, 4); sndlen += 4; - memcpy(sndbuf + sndlen, XML_content, length); sndlen += length; - xmlFree(XML_content); - xmlFreeDoc(plist); - plist = NULL; + free(XML_content); + XML_content = NULL; + plist_free(dict); + dict = NULL; log_debug_buffer(sndbuf, sndlen); - iphone_mux_send(client->connection, sndbuf, sndlen, &bytes); + iphone_mux_send(client->connection, sndbuf, sndlen, (uint32_t*)&bytes); if (bytes <= 0) { np_unlock(client); return bytes; } np_unlock(client); - return bytes; + return IPHONE_E_SUCCESS; } diff --git a/src/lockdown.c b/src/lockdown.c index 73a8bbc..707994d 100644 --- a/src/lockdown.c +++ b/src/lockdown.c @@ -31,6 +31,8 @@ #include #include +#include + const ASN1_ARRAY_TYPE pkcs1_asn1_tab[] = { {"PKCS1", 536872976, 0}, {0, 1073741836, 0}, @@ -97,60 +99,66 @@ iphone_lckd_client_t new_lockdownd_client(iphone_device_t phone) * * @param control The lockdown client */ -static void iphone_lckd_stop_session(iphone_lckd_client_t control) +static iphone_error_t iphone_lckd_stop_session(iphone_lckd_client_t control) { if (!control) - return; // IPHONE_E_INVALID_ARG; - xmlDocPtr plist = new_plist(); - xmlNode *dict, *key; - char **dictionary; - int bytes = 0, i = 0; + return IPHONE_E_INVALID_ARG; + + uint32_t bytes = 0; iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; - log_debug_msg("lockdownd_stop_session() called\n"); - dict = add_child_to_plist(plist, "dict", "\n", NULL, 0); - key = add_key_str_dict_element(plist, dict, "Request", "StopSession", 1); - key = add_key_str_dict_element(plist, dict, "SessionID", control->session_id, 1); + plist_t dict = plist_new_dict(); + plist_add_sub_key_el(dict, "Request"); + plist_add_sub_string_el(dict, "StopSession"); + plist_add_sub_key_el(dict, "SessionID"); + plist_add_sub_string_el(dict, control->session_id); - char *XML_content; - uint32 length; + log_debug_msg("lockdownd_stop_session() called\n"); + char *XML_content = NULL; + uint32_t length = 0; - xmlDocDumpMemory(plist, (xmlChar **) & XML_content, &length); + plist_to_xml(dict, &XML_content, &length); ret = iphone_lckd_send(control, XML_content, length, &bytes); - xmlFree(XML_content); - xmlFreeDoc(plist); - plist = NULL; + free(XML_content); + XML_content = NULL; + plist_free(dict); + dict = NULL; + ret = iphone_lckd_recv(control, &XML_content, &bytes); + plist_from_xml(XML_content, bytes, &dict); - plist = xmlReadMemory(XML_content, bytes, NULL, NULL, 0); - if (!plist) { + if (!dict) { log_debug_msg("lockdownd_stop_session(): IPHONE_E_PLIST_ERROR\n"); - return; //IPHONE_E_PLIST_ERROR; + return IPHONE_E_PLIST_ERROR; } - dict = xmlDocGetRootElement(plist); - for (dict = dict->children; dict; dict = dict->next) { - if (!xmlStrcmp(dict->name, "dict")) - break; + + plist_t query_node = plist_find_node_by_string(dict, "StopSession"); + plist_t result_node = plist_get_next_sibling(query_node); + plist_t value_node = plist_get_next_sibling(result_node); + + char *result_value = NULL; + char *value_value = NULL; + + if (plist_get_node_type(result_node) == PLIST_KEY) { + plist_get_key_val(result_node, &result_value); } - if (!dict) { - log_debug_msg("lockdownd_stop_session(): IPHONE_E_DICT_ERROR\n"); - return; //IPHONE_E_DICT_ERROR; + if (plist_get_node_type(value_node) == PLIST_STRING) { + plist_get_string_val(value_node, &value_value); } - dictionary = read_dict_element_strings(dict); - xmlFreeDoc(plist); - free(XML_content); - for (i = 0; dictionary[i]; i += 2) { - if (!strcmp(dictionary[i], "Result") && !strcmp(dictionary[i + 1], "Success")) { - log_debug_msg("lockdownd_stop_session(): success\n"); - ret = IPHONE_E_SUCCESS; - break; - } + if (result_value && value_value + && !strcmp(result_value, "Result") && !strcmp(value_value, "Success")) { + log_debug_msg("lockdownd_stop_session(): success\n"); + ret = IPHONE_E_SUCCESS; } - free_dictionary(dictionary); - return; //ret; + if (result_value) + free(result_value); + if (value_value) + free(value_value); + + return ret; } /** @@ -261,7 +269,7 @@ iphone_error_t iphone_lckd_send(iphone_lckd_client_t client, char *raw_data, uin if (!client || !raw_data || length == 0 || !sent_bytes) return IPHONE_E_INVALID_ARG; char *real_query; - int bytes; + uint32_t bytes = 0; iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; real_query = (char *) malloc(sizeof(char) * (length + 4)); @@ -295,49 +303,57 @@ iphone_error_t lockdownd_hello(iphone_lckd_client_t control) { if (!control) return IPHONE_E_INVALID_ARG; - xmlDocPtr plist = new_plist(); - xmlNode *dict, *key; - char **dictionary; - int bytes = 0, i = 0; + + uint32_t bytes = 0; iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; + plist_t dict = plist_new_dict(); + plist_add_sub_key_el(dict, "Request"); + plist_add_sub_string_el(dict, "QueryType"); + log_debug_msg("lockdownd_hello() called\n"); - dict = add_child_to_plist(plist, "dict", "\n", NULL, 0); - key = add_key_str_dict_element(plist, dict, "Request", "QueryType", 1); - char *XML_content; - uint32 length; + char *XML_content = NULL; + uint32_t length = 0; - xmlDocDumpMemory(plist, (xmlChar **) & XML_content, &length); + plist_to_xml(dict, &XML_content, &length); ret = iphone_lckd_send(control, XML_content, length, &bytes); - xmlFree(XML_content); - xmlFreeDoc(plist); - plist = NULL; + free(XML_content); + XML_content = NULL; + plist_free(dict); + dict = NULL; + ret = iphone_lckd_recv(control, &XML_content, &bytes); + plist_from_xml(XML_content, bytes, &dict); - plist = xmlReadMemory(XML_content, bytes, NULL, NULL, 0); - if (!plist) + if (!dict) return IPHONE_E_PLIST_ERROR; - dict = xmlDocGetRootElement(plist); - for (dict = dict->children; dict; dict = dict->next) { - if (!xmlStrcmp(dict->name, "dict")) - break; + + plist_t query_node = plist_find_node_by_string(dict, "QueryType"); + plist_t result_node = plist_get_next_sibling(query_node); + plist_t value_node = plist_get_next_sibling(result_node); + + char *result_value = NULL; + char *value_value = NULL; + + if (plist_get_node_type(result_node) == PLIST_KEY) { + plist_get_key_val(result_node, &result_value); + } + if (plist_get_node_type(value_node) == PLIST_STRING) { + plist_get_string_val(value_node, &value_value); } - if (!dict) - return IPHONE_E_DICT_ERROR; - dictionary = read_dict_element_strings(dict); - xmlFreeDoc(plist); - free(XML_content); - for (i = 0; dictionary[i]; i += 2) { - if (!strcmp(dictionary[i], "Result") && !strcmp(dictionary[i + 1], "Success")) { - log_debug_msg("lockdownd_hello(): success\n"); - ret = IPHONE_E_SUCCESS; - break; - } + if (result_value && value_value + && !strcmp(result_value, "Result") && !strcmp(value_value, "Success")) { + log_debug_msg("lockdownd_hello(): success\n"); + ret = IPHONE_E_SUCCESS; } - free_dictionary(dictionary); + if (result_value) + free(result_value); + if (value_value) + free(value_value); + return ret; } @@ -349,32 +365,32 @@ iphone_error_t lockdownd_hello(iphone_lckd_client_t control) * * @return IPHONE_E_SUCCESS on success. */ -iphone_error_t lockdownd_generic_get_value(iphone_lckd_client_t control, const char *req_key, const char *req_string, - char **value) +iphone_error_t lockdownd_generic_get_value(iphone_lckd_client_t control, const char *req_key, const char *req_string, gnutls_datum_t *value) { - if (!control || !req_key || !value || (value && *value)) + if (!control || !req_key || !value || value->data) return IPHONE_E_INVALID_ARG; - xmlDocPtr plist = new_plist(); - xmlNode *dict = NULL; - xmlNode *key = NULL;; - char **dictionary = NULL; - int bytes = 0, i = 0; + + plist_t dict = NULL; + uint32_t bytes = 0; char *XML_content = NULL; - uint32 length = 0; + uint32_t length = 0; iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; /* Setup DevicePublicKey request plist */ - dict = add_child_to_plist(plist, "dict", "\n", NULL, 0); - key = add_key_str_dict_element(plist, dict, req_key, req_string, 1); - key = add_key_str_dict_element(plist, dict, "Request", "GetValue", 1); - xmlDocDumpMemory(plist, (xmlChar **) & XML_content, &length); + dict = plist_new_dict(); + plist_add_sub_key_el(dict, req_key); + plist_add_sub_string_el(dict, req_string); + plist_add_sub_key_el(dict, "Request"); + plist_add_sub_string_el(dict, "GetValue"); + plist_to_xml(dict, &XML_content, &length); /* send to iPhone */ ret = iphone_lckd_send(control, XML_content, length, &bytes); - xmlFree(XML_content); - xmlFreeDoc(plist); - plist = NULL; + free(XML_content); + XML_content = NULL; + plist_free(dict); + dict = NULL; if (ret != IPHONE_E_SUCCESS) return ret; @@ -385,38 +401,76 @@ iphone_error_t lockdownd_generic_get_value(iphone_lckd_client_t control, const c if (ret != IPHONE_E_SUCCESS) return ret; - plist = xmlReadMemory(XML_content, bytes, NULL, NULL, 0); - if (!plist) + plist_from_xml(XML_content, bytes, &dict); + if (!dict) return IPHONE_E_PLIST_ERROR; - dict = xmlDocGetRootElement(plist); - for (dict = dict->children; dict; dict = dict->next) { - if (!xmlStrcmp(dict->name, "dict")) - break; + + plist_t query_node = plist_find_node_by_string(dict, "GetValue"); + plist_t result_key_node = plist_get_next_sibling(query_node); + plist_t result_value_node = plist_get_next_sibling(result_key_node); + + char *result_key = NULL; + char *result_value = NULL; + + if (plist_get_node_type(result_key_node) == PLIST_KEY) { + plist_get_key_val(result_key_node, &result_key); + } + if (plist_get_node_type(result_value_node) == PLIST_STRING) { + plist_get_string_val(result_value_node, &result_value); } - if (!dict) - return IPHONE_E_DICT_ERROR; - /* Parse xml to check success and to find public key */ - dictionary = read_dict_element_strings(dict); - xmlFreeDoc(plist); - free(XML_content); + if (result_key && result_value + && !strcmp(result_key, "Result") && !strcmp(result_value, "Success")) { + log_debug_msg("lockdownd_generic_get_value(): success\n"); + ret = IPHONE_E_SUCCESS; + } - int success = 0; - for (i = 0; dictionary[i]; i += 2) { - if (!strcmp(dictionary[i], "Result") && !strcmp(dictionary[i + 1], "Success")) { - success = 1; - } - if (!strcmp(dictionary[i], "Value")) { - *value = strdup(dictionary[i + 1]); - } + if (result_value) + free(result_value); + if (result_key) + free(result_key); + + if (ret != IPHONE_E_SUCCESS) { + return IPHONE_E_DICT_ERROR; } - if (dictionary) { - free_dictionary(dictionary); - dictionary = NULL; + plist_t value_key_node = plist_get_next_sibling(result_value_node); + plist_t value_value_node = plist_get_next_sibling(value_key_node); + plist_type value_value_type; + char *value_key = NULL; + char *value_value = NULL; + uint64_t valval_length = 0; + + if (plist_get_node_type(value_key_node) == PLIST_KEY) { + plist_get_key_val(value_key_node, &value_key); + } + value_value_type = plist_get_node_type(value_value_node); + switch (value_value_type) { + case PLIST_STRING: + plist_get_string_val(value_value_node, &value_value); + if (value_value) { + valval_length = strlen(value_value); + } + break; + case PLIST_DATA: + plist_get_data_val(value_value_node, &value_value, &valval_length); + break; + default: + break; } - if (success) + + if (value_key && !strcmp(value_key, "Value")) { + log_debug_msg("lockdownd_generic_get_value(): success\n"); + value->data = (unsigned char*)value_value; + value->size = valval_length; ret = IPHONE_E_SUCCESS; + } + + if (value_key) + free(value_key); + + plist_free(dict); + free(XML_content); return ret; } @@ -428,7 +482,10 @@ iphone_error_t lockdownd_generic_get_value(iphone_lckd_client_t control, const c */ iphone_error_t lockdownd_get_device_uid(iphone_lckd_client_t control, char **uid) { - return lockdownd_generic_get_value(control, "Key", "UniqueDeviceID", uid); + gnutls_datum_t temp = { NULL, 0 }; + iphone_error_t res = lockdownd_generic_get_value(control, "Key", "UniqueDeviceID", &temp); + *uid = (char*)temp.data; + return res; } /** Askes for the device's public key. Part of the lockdownd handshake. @@ -437,7 +494,7 @@ iphone_error_t lockdownd_get_device_uid(iphone_lckd_client_t control, char **uid * * @return 1 on success and 0 on failure. */ -iphone_error_t lockdownd_get_device_public_key(iphone_lckd_client_t control, char **public_key) +iphone_error_t lockdownd_get_device_public_key(iphone_lckd_client_t control, gnutls_datum_t *public_key) { return lockdownd_generic_get_value(control, "Key", "DevicePublicKey", public_key); } @@ -513,51 +570,59 @@ iphone_error_t iphone_lckd_new_client(iphone_device_t device, iphone_lckd_client iphone_error_t lockdownd_pair_device(iphone_lckd_client_t control, char *uid, char *host_id) { iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; - xmlDocPtr plist = new_plist(); - xmlNode *dict = NULL; - xmlNode *dictRecord = NULL; - char **dictionary = NULL; - int bytes = 0, i = 0; + plist_t dict = NULL; + plist_t dict_record = NULL; + uint32_t bytes = 0; char *XML_content = NULL; - uint32 length = 0; + uint32_t length = 0; - char *device_cert_b64 = NULL; - char *host_cert_b64 = NULL; - char *root_cert_b64 = NULL; - char *public_key_b64 = NULL; + gnutls_datum_t device_cert = { NULL, 0 }; + gnutls_datum_t host_cert = { NULL, 0 }; + gnutls_datum_t root_cert = { NULL, 0 }; + gnutls_datum_t public_key = { NULL, 0 }; - ret = lockdownd_get_device_public_key(control, &public_key_b64); + ret = lockdownd_get_device_public_key(control, &public_key); if (ret != IPHONE_E_SUCCESS) { log_debug_msg("Device refused to send public key.\n"); return ret; } - ret = lockdownd_gen_pair_cert(public_key_b64, &device_cert_b64, &host_cert_b64, &root_cert_b64); + ret = lockdownd_gen_pair_cert(public_key, &device_cert, &host_cert, &root_cert); if (ret != IPHONE_E_SUCCESS) { - free(public_key_b64); + free(public_key.data); return ret; } /* Setup Pair request plist */ - dict = add_child_to_plist(plist, "dict", "\n", NULL, 0); - dictRecord = add_key_dict_node(plist, dict, "PairRecord", "\n", 1); - //dictRecord = add_child_to_plist(plist, "dict", "\n", NULL, 1); - add_key_data_dict_element(plist, dictRecord, "DeviceCertificate", device_cert_b64, 2); - add_key_data_dict_element(plist, dictRecord, "HostCertificate", host_cert_b64, 2); - add_key_str_dict_element(plist, dictRecord, "HostID", host_id, 2); - add_key_data_dict_element(plist, dictRecord, "RootCertificate", root_cert_b64, 2); - add_key_str_dict_element(plist, dict, "Request", "Pair", 1); + dict = plist_new_dict(); + plist_add_sub_key_el(dict, "PairRecord"); + dict_record = plist_new_dict(); + plist_add_sub_node(dict, dict_record); + + plist_add_sub_key_el(dict_record, "DeviceCertificate"); + plist_add_sub_data_el(dict_record, (const char*)device_cert.data, device_cert.size); - xmlDocDumpMemory(plist, (xmlChar **) & XML_content, &length); + plist_add_sub_key_el(dict_record, "HostCertificate"); + plist_add_sub_data_el(dict_record, (const char*)host_cert.data, host_cert.size); - printf("XML Pairing request : %s\n", XML_content); + plist_add_sub_key_el(dict_record, "HostID"); + plist_add_sub_string_el(dict_record, host_id); + + plist_add_sub_key_el(dict_record, "RootCertificate"); + plist_add_sub_data_el(dict_record, (const char*)root_cert.data, root_cert.size); + + plist_add_sub_key_el(dict_record, "Request"); + plist_add_sub_string_el(dict_record, "Pair"); + + plist_to_xml(dict, &XML_content, &length); + log_debug_msg("XML Pairing request :\nsize : %i\nxml :\n %s", length, XML_content); /* send to iPhone */ ret = iphone_lckd_send(control, XML_content, length, &bytes); - xmlFree(XML_content); - xmlFreeDoc(plist); - plist = NULL; + free(XML_content); + plist_free(dict); + dict = NULL; if (ret != IPHONE_E_SUCCESS) return ret; @@ -572,48 +637,40 @@ iphone_error_t lockdownd_pair_device(iphone_lckd_client_t control, char *uid, ch log_debug_msg(XML_content); log_debug_msg("\n\n"); - plist = xmlReadMemory(XML_content, bytes, NULL, NULL, 0); - if (!plist) { - free(public_key_b64); - return IPHONE_E_PLIST_ERROR; - } - dict = xmlDocGetRootElement(plist); - for (dict = dict->children; dict; dict = dict->next) { - if (!xmlStrcmp(dict->name, "dict")) - break; - } + plist_from_xml(XML_content, bytes, &dict); if (!dict) { - free(public_key_b64); - return IPHONE_E_DICT_ERROR; + free(public_key.data); + return IPHONE_E_PLIST_ERROR; } - /* Parse xml to check success and to find public key */ - dictionary = read_dict_element_strings(dict); - xmlFreeDoc(plist); - free(XML_content); + plist_t query_node = plist_find_node_by_string(dict, "Pair"); + plist_t result_key_node = plist_get_next_sibling(query_node); + plist_t result_value_node = plist_get_next_sibling(result_key_node); - int success = 0; - for (i = 0; dictionary[i]; i += 2) { - if (!strcmp(dictionary[i], "Result") && !strcmp(dictionary[i + 1], "Success")) { - success = 1; - } + char *result_key = NULL; + char *result_value = NULL; + + if (plist_get_node_type(result_key_node) == PLIST_KEY) { + plist_get_key_val(result_key_node, &result_key); + } + if (plist_get_node_type(result_value_node) == PLIST_STRING) { + plist_get_string_val(result_value_node, &result_value); } - if (dictionary) { - free_dictionary(dictionary); - dictionary = NULL; + if (result_key && result_value && !strcmp(result_key, "Result") && !strcmp(result_value, "Success")) { + ret = IPHONE_E_SUCCESS; } /* store public key in config if pairing succeeded */ - if (success) { + if (ret == IPHONE_E_SUCCESS) { log_debug_msg("lockdownd_pair_device: pair success\n"); - store_device_public_key(uid, public_key_b64); + store_device_public_key(uid, public_key); ret = IPHONE_E_SUCCESS; } else { log_debug_msg("lockdownd_pair_device: pair failure\n"); ret = IPHONE_E_PAIRING_FAILED; } - free(public_key_b64); + free(public_key.data); return ret; } @@ -623,58 +680,58 @@ iphone_error_t lockdownd_pair_device(iphone_lckd_client_t control, char *uid, ch * * @param control The lockdown client */ -void lockdownd_close(iphone_lckd_client_t control) +iphone_error_t lockdownd_close(iphone_lckd_client_t control) { if (!control) - return; // IPHONE_E_INVALID_ARG; - xmlDocPtr plist = new_plist(); - xmlNode *dict, *key; - char **dictionary; - int bytes = 0, i = 0; + return IPHONE_E_INVALID_ARG; + + uint32_t bytes = 0; iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; + plist_t dict = plist_new_dict(); + plist_add_sub_key_el(dict, "Request"); + plist_add_sub_string_el(dict, "Goodbye"); + log_debug_msg("lockdownd_close() called\n"); - dict = add_child_to_plist(plist, "dict", "\n", NULL, 0); - key = add_key_str_dict_element(plist, dict, "Request", "Goodbye", 1); - char *XML_content; - uint32 length; + char *XML_content = NULL; + uint32_t length = 0; - xmlDocDumpMemory(plist, (xmlChar **) & XML_content, &length); + plist_to_xml(dict, &XML_content, &length); ret = iphone_lckd_send(control, XML_content, length, &bytes); - xmlFree(XML_content); - xmlFreeDoc(plist); - plist = NULL; + free(XML_content); + XML_content = NULL; + plist_free(dict); + dict = NULL; + ret = iphone_lckd_recv(control, &XML_content, &bytes); + plist_from_xml(XML_content, bytes, &dict); - plist = xmlReadMemory(XML_content, bytes, NULL, NULL, 0); - if (!plist) { + if (!dict) { log_debug_msg("lockdownd_close(): IPHONE_E_PLIST_ERROR\n"); - return; //IPHONE_E_PLIST_ERROR; + return IPHONE_E_PLIST_ERROR; } - dict = xmlDocGetRootElement(plist); - for (dict = dict->children; dict; dict = dict->next) { - if (!xmlStrcmp(dict->name, "dict")) - break; + + plist_t query_node = plist_find_node_by_string(dict, "Goodbye"); + plist_t result_node = plist_get_next_sibling(query_node); + plist_t value_node = plist_get_next_sibling(result_node); + + char *result_value = NULL; + char *value_value = NULL; + + if (plist_get_node_type(result_node) == PLIST_KEY) { + plist_get_key_val(result_node, &result_value); } - if (!dict) { - log_debug_msg("lockdownd_close(): IPHONE_E_DICT_ERROR\n"); - return; //IPHONE_E_DICT_ERROR; + if (plist_get_node_type(value_node) == PLIST_STRING) { + plist_get_string_val(value_node, &value_value); } - dictionary = read_dict_element_strings(dict); - xmlFreeDoc(plist); - free(XML_content); - for (i = 0; dictionary[i]; i += 2) { - if (!strcmp(dictionary[i], "Result") && !strcmp(dictionary[i + 1], "Success")) { - log_debug_msg("lockdownd_close(): success\n"); - ret = IPHONE_E_SUCCESS; - break; - } + if (result_value && value_value && !strcmp(result_value, "Result") && !strcmp(value_value, "Success")) { + log_debug_msg("lockdownd_close(): success\n"); + ret = IPHONE_E_SUCCESS; } - free_dictionary(dictionary); - return; //ret; + return ret; } /** Generates the device certificate from the public key as well as the host @@ -682,25 +739,18 @@ void lockdownd_close(iphone_lckd_client_t control) * * @return IPHONE_E_SUCCESS on success. */ -iphone_error_t lockdownd_gen_pair_cert(char *public_key_b64, char **device_cert_b64, char **host_cert_b64, - char **root_cert_b64) +iphone_error_t lockdownd_gen_pair_cert(gnutls_datum_t public_key, gnutls_datum_t *odevice_cert, gnutls_datum_t *ohost_cert, gnutls_datum_t *oroot_cert) { - if (!public_key_b64 || !device_cert_b64 || !host_cert_b64 || !root_cert_b64) + if (!public_key.data || !odevice_cert || !ohost_cert || !oroot_cert) return IPHONE_E_INVALID_ARG; iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; gnutls_datum_t modulus = { NULL, 0 }; gnutls_datum_t exponent = { NULL, 0 }; - /* first decode base64 public_key */ - gnutls_datum_t pem_pub_key; - gsize decoded_size; - pem_pub_key.data = g_base64_decode(public_key_b64, &decoded_size); - pem_pub_key.size = decoded_size; - /* now decode the PEM encoded key */ gnutls_datum_t der_pub_key; - if (GNUTLS_E_SUCCESS == gnutls_pem_base64_decode_alloc("RSA PUBLIC KEY", &pem_pub_key, &der_pub_key)) { + if (GNUTLS_E_SUCCESS == gnutls_pem_base64_decode_alloc("RSA PUBLIC KEY", &public_key, &der_pub_key)) { /* initalize asn.1 parser */ ASN1_TYPE pkcs1 = ASN1_TYPE_EMPTY; @@ -712,14 +762,14 @@ iphone_error_t lockdownd_gen_pair_cert(char *public_key_b64, char **device_cert_ if (ASN1_SUCCESS == asn1_der_decoding(&asn1_pub_key, der_pub_key.data, der_pub_key.size, NULL)) { /* get size to read */ - int ret1 = asn1_read_value(asn1_pub_key, "modulus", NULL, &modulus.size); - int ret2 = asn1_read_value(asn1_pub_key, "publicExponent", NULL, &exponent.size); + int ret1 = asn1_read_value(asn1_pub_key, "modulus", NULL, (int*)&modulus.size); + int ret2 = asn1_read_value(asn1_pub_key, "publicExponent", NULL, (int*)&exponent.size); modulus.data = gnutls_malloc(modulus.size); exponent.data = gnutls_malloc(exponent.size); - ret1 = asn1_read_value(asn1_pub_key, "modulus", modulus.data, &modulus.size); - ret2 = asn1_read_value(asn1_pub_key, "publicExponent", exponent.data, &exponent.size); + 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 = IPHONE_E_SUCCESS; } @@ -734,7 +784,7 @@ iphone_error_t lockdownd_gen_pair_cert(char *public_key_b64, char **device_cert_ if (IPHONE_E_SUCCESS == ret && 0 != modulus.size && 0 != exponent.size) { gnutls_global_init(); - gnutls_datum_t essentially_null = { strdup("abababababababab"), strlen("abababababababab") }; + gnutls_datum_t essentially_null = { (unsigned char*)strdup("abababababababab"), strlen("abababababababab") }; gnutls_x509_privkey_t fake_privkey, root_privkey; gnutls_x509_crt_t dev_cert, root_cert, host_cert; @@ -784,10 +834,18 @@ iphone_error_t lockdownd_gen_pair_cert(char *public_key_b64, char **device_cert_ dev_pem.data = gnutls_malloc(dev_pem.size); gnutls_x509_crt_export(dev_cert, GNUTLS_X509_FMT_PEM, dev_pem.data, &dev_pem.size); - /* now encode certificates for output */ - *device_cert_b64 = g_base64_encode(dev_pem.data, dev_pem.size); - *host_cert_b64 = g_base64_encode(pem_host_cert.data, pem_host_cert.size); - *root_cert_b64 = g_base64_encode(pem_root_cert.data, pem_root_cert.size); + /* copy buffer for output */ + odevice_cert->data = malloc(dev_pem.size); + memcpy(odevice_cert->data, dev_pem.data, dev_pem.size); + odevice_cert->size = dev_pem.size; + + ohost_cert->data = malloc(pem_host_cert.size); + memcpy(ohost_cert->data, pem_host_cert.data, pem_host_cert.size); + ohost_cert->size = pem_host_cert.size; + + oroot_cert->data = malloc(pem_root_cert.size); + memcpy(oroot_cert->data, pem_root_cert.data, pem_root_cert.size); + oroot_cert->size = pem_root_cert.size; } gnutls_free(pem_root_priv.data); gnutls_free(pem_root_cert.data); @@ -799,7 +857,6 @@ iphone_error_t lockdownd_gen_pair_cert(char *public_key_b64, char **device_cert_ gnutls_free(exponent.data); gnutls_free(der_pub_key.data); - g_free(pem_pub_key.data); return ret; } @@ -813,124 +870,131 @@ iphone_error_t lockdownd_gen_pair_cert(char *public_key_b64, char **device_cert_ */ iphone_error_t lockdownd_start_SSL_session(iphone_lckd_client_t control, const char *HostID) { - xmlDocPtr plist = new_plist(); - xmlNode *dict = add_child_to_plist(plist, "dict", "\n", NULL, 0); - xmlNode *key; - char *what2send = NULL, **dictionary = NULL; - uint32 len = 0, bytes = 0, return_me = 0, i = 0; - iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; - // end variables + plist_t dict = NULL; + char *XML_content = NULL; + uint32_t length = 0, bytes = 0, return_me = 0; + iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; control->session_id[0] = '\0'; - key = add_key_str_dict_element(plist, dict, "HostID", HostID, 1); - if (!key) { - log_debug_msg("Couldn't add a key.\n"); - xmlFreeDoc(plist); - return IPHONE_E_DICT_ERROR; - } - key = add_key_str_dict_element(plist, dict, "Request", "StartSession", 1); - if (!key) { - log_debug_msg("Couldn't add a key.\n"); - xmlFreeDoc(plist); - return IPHONE_E_DICT_ERROR; - } + /* Setup DevicePublicKey request plist */ + dict = plist_new_dict(); + plist_add_sub_key_el(dict, "HostID"); + plist_add_sub_string_el(dict, HostID); + plist_add_sub_key_el(dict, "Request"); + plist_add_sub_string_el(dict, "StartSession"); + plist_to_xml(dict, &XML_content, &length); - xmlDocDumpMemory(plist, (xmlChar **) & what2send, &len); - ret = iphone_lckd_send(control, what2send, len, &bytes); + ret = iphone_lckd_send(control, XML_content, length, &bytes); - xmlFree(what2send); - xmlFreeDoc(plist); + free(XML_content); + XML_content = NULL; + plist_free(dict); + dict = NULL; if (ret != IPHONE_E_SUCCESS) return ret; if (bytes > 0) { - ret = iphone_lckd_recv(control, &what2send, &len); - plist = xmlReadMemory(what2send, len, NULL, NULL, 0); - dict = xmlDocGetRootElement(plist); + ret = iphone_lckd_recv(control, &XML_content, &bytes); + plist_from_xml(XML_content, bytes, &dict); + if (XML_content) + free(XML_content); if (!dict) - return IPHONE_E_DICT_ERROR; - for (dict = dict->children; dict; dict = dict->next) { - if (!xmlStrcmp(dict->name, "dict")) - break; + return IPHONE_E_PLIST_ERROR; + + plist_t query_node = plist_find_node_by_string(dict, "StartSession"); + plist_t result_key_node = plist_get_next_sibling(query_node); + plist_t result_value_node = plist_get_next_sibling(result_key_node); + + char *result_key = NULL; + char *result_value = NULL; + + if (plist_get_node_type(result_key_node) == PLIST_KEY) { + plist_get_key_val(result_key_node, &result_key); } - dictionary = read_dict_element_strings(dict); - xmlFreeDoc(plist); - free(what2send); + if (plist_get_node_type(result_value_node) == PLIST_STRING) { + plist_get_string_val(result_value_node, &result_value); + } + + plist_free(dict); + dict = NULL; ret = IPHONE_E_SSL_ERROR; - for (i = 0; dictionary[i]; i += 2) { - if (!strcmp(dictionary[i], "Result") && !strcmp(dictionary[i + 1], "Success")) { - // Set up GnuTLS... - //gnutls_anon_client_credentials_t anoncred; - gnutls_certificate_credentials_t xcred; - - log_debug_msg("We started the session OK, now trying GnuTLS\n"); - errno = 0; - gnutls_global_init(); - //gnutls_anon_allocate_client_credentials(&anoncred); - gnutls_certificate_allocate_credentials(&xcred); - gnutls_certificate_set_x509_trust_file(xcred, "hostcert.pem", GNUTLS_X509_FMT_PEM); - gnutls_init(control->ssl_session, GNUTLS_CLIENT); - { - int protocol_priority[16] = { GNUTLS_SSL3, 0 }; - int kx_priority[16] = { GNUTLS_KX_ANON_DH, GNUTLS_KX_RSA, 0 }; - int cipher_priority[16] = { GNUTLS_CIPHER_AES_128_CBC, GNUTLS_CIPHER_AES_256_CBC, 0 }; - int mac_priority[16] = { GNUTLS_MAC_SHA1, GNUTLS_MAC_MD5, 0 }; - int comp_priority[16] = { GNUTLS_COMP_NULL, 0 }; - - gnutls_cipher_set_priority(*control->ssl_session, cipher_priority); - gnutls_compression_set_priority(*control->ssl_session, comp_priority); - gnutls_kx_set_priority(*control->ssl_session, kx_priority); - gnutls_protocol_set_priority(*control->ssl_session, protocol_priority); - gnutls_mac_set_priority(*control->ssl_session, mac_priority); - - } - gnutls_credentials_set(*control->ssl_session, GNUTLS_CRD_CERTIFICATE, xcred); // this part is killing me. - - log_debug_msg("GnuTLS step 1...\n"); - gnutls_transport_set_ptr(*control->ssl_session, (gnutls_transport_ptr_t) control); - log_debug_msg("GnuTLS step 2...\n"); - gnutls_transport_set_push_function(*control->ssl_session, (gnutls_push_func) & lockdownd_secuwrite); - log_debug_msg("GnuTLS step 3...\n"); - gnutls_transport_set_pull_function(*control->ssl_session, (gnutls_pull_func) & lockdownd_securead); - log_debug_msg("GnuTLS step 4 -- now handshaking...\n"); - - if (errno) - log_debug_msg("WARN: errno says %s before handshake!\n", strerror(errno)); - return_me = gnutls_handshake(*control->ssl_session); - log_debug_msg("GnuTLS handshake done...\n"); - - if (return_me != GNUTLS_E_SUCCESS) { - log_debug_msg("GnuTLS reported something wrong.\n"); - gnutls_perror(return_me); - log_debug_msg("oh.. errno says %s\n", strerror(errno)); - return IPHONE_E_SSL_ERROR; - } else { - control->in_SSL = 1; - ret = IPHONE_E_SUCCESS; - } - } else if (!strcmp(dictionary[i], "SessionID")) { + if (result_key && result_value && !strcmp(result_key, "Result") && !strcmp(result_value, "Success")) { + // Set up GnuTLS... + //gnutls_anon_client_credentials_t anoncred; + gnutls_certificate_credentials_t xcred; + + log_debug_msg("We started the session OK, now trying GnuTLS\n"); + errno = 0; + gnutls_global_init(); + //gnutls_anon_allocate_client_credentials(&anoncred); + gnutls_certificate_allocate_credentials(&xcred); + gnutls_certificate_set_x509_trust_file(xcred, "hostcert.pem", GNUTLS_X509_FMT_PEM); + gnutls_init(control->ssl_session, GNUTLS_CLIENT); + { + int protocol_priority[16] = { GNUTLS_SSL3, 0 }; + int kx_priority[16] = { GNUTLS_KX_ANON_DH, GNUTLS_KX_RSA, 0 }; + int cipher_priority[16] = { GNUTLS_CIPHER_AES_128_CBC, GNUTLS_CIPHER_AES_256_CBC, 0 }; + int mac_priority[16] = { GNUTLS_MAC_SHA1, GNUTLS_MAC_MD5, 0 }; + int comp_priority[16] = { GNUTLS_COMP_NULL, 0 }; + + gnutls_cipher_set_priority(*control->ssl_session, cipher_priority); + gnutls_compression_set_priority(*control->ssl_session, comp_priority); + gnutls_kx_set_priority(*control->ssl_session, kx_priority); + gnutls_protocol_set_priority(*control->ssl_session, protocol_priority); + gnutls_mac_set_priority(*control->ssl_session, mac_priority); + + } + gnutls_credentials_set(*control->ssl_session, GNUTLS_CRD_CERTIFICATE, xcred); // this part is killing me. + + log_debug_msg("GnuTLS step 1...\n"); + gnutls_transport_set_ptr(*control->ssl_session, (gnutls_transport_ptr_t) control); + log_debug_msg("GnuTLS step 2...\n"); + gnutls_transport_set_push_function(*control->ssl_session, (gnutls_push_func) & lockdownd_secuwrite); + log_debug_msg("GnuTLS step 3...\n"); + gnutls_transport_set_pull_function(*control->ssl_session, (gnutls_pull_func) & lockdownd_securead); + log_debug_msg("GnuTLS step 4 -- now handshaking...\n"); + + if (errno) + log_debug_msg("WARN: errno says %s before handshake!\n", strerror(errno)); + return_me = gnutls_handshake(*control->ssl_session); + log_debug_msg("GnuTLS handshake done...\n"); + + if (return_me != GNUTLS_E_SUCCESS) { + log_debug_msg("GnuTLS reported something wrong.\n"); + gnutls_perror(return_me); + log_debug_msg("oh.. errno says %s\n", strerror(errno)); + return IPHONE_E_SSL_ERROR; + } else { + control->in_SSL = 1; + ret = IPHONE_E_SUCCESS; + } + } + //store session id + plist_t session_node = plist_find_node_by_key(dict, "SessionID"); + if (session_node) { + + char *session_id = NULL; + plist_t session_node_val = plist_get_next_sibling(session_node); + + if (plist_get_node_type(session_node_val) == PLIST_STRING) { + plist_get_string_val(session_node_val, &session_id); + } + if (session_id) { // we need to store the session ID for StopSession - strcpy(control->session_id, dictionary[i + 1]); + strcpy(control->session_id, session_id); log_debug_msg("SessionID: %s\n", control->session_id); - free_dictionary(dictionary); return ret; } } + if (ret == IPHONE_E_SUCCESS) { log_debug_msg("Failed to get SessionID!\n"); return ret; } log_debug_msg("Apparently failed negotiating with lockdownd.\n"); - log_debug_msg("Responding dictionary: \n"); - for (i = 0; dictionary[i]; i += 2) { - log_debug_msg("\t%s: %s\n", dictionary[i], dictionary[i + 1]); - } - - - free_dictionary(dictionary); return IPHONE_E_SSL_ERROR; } else { log_debug_msg("Didn't get enough bytes.\n"); @@ -948,7 +1012,7 @@ iphone_error_t lockdownd_start_SSL_session(iphone_lckd_client_t control, const c */ ssize_t lockdownd_secuwrite(gnutls_transport_ptr_t transport, char *buffer, size_t length) { - int bytes = 0; + uint32_t bytes = 0; iphone_lckd_client_t control; control = (iphone_lckd_client_t) transport; log_debug_msg("lockdownd_secuwrite() called\n"); @@ -970,7 +1034,8 @@ ssize_t lockdownd_secuwrite(gnutls_transport_ptr_t transport, char *buffer, size */ ssize_t lockdownd_securead(gnutls_transport_ptr_t transport, char *buffer, size_t length) { - int bytes = 0, pos_start_fill = 0; + uint32_t bytes = 0; + int pos_start_fill = 0; int tbytes = 0; int this_len = length; iphone_error_t res; @@ -1038,81 +1103,88 @@ iphone_error_t iphone_lckd_start_service(iphone_lckd_client_t client, const char if (!client->in_SSL && !lockdownd_start_SSL_session(client, host_id)) return IPHONE_E_SSL_ERROR; - char *XML_query, **dictionary; - uint32 length, i = 0, port_loc = 0, bytes = 0; - uint8 result = 0; + plist_t dict = NULL; + char *XML_content = NULL; + uint32_t length, port_loc = 0, bytes = 0; iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; free(host_id); host_id = NULL; - xmlDocPtr plist = new_plist(); - xmlNode *dict = add_child_to_plist(plist, "dict", "\n", NULL, 0); - xmlNode *key; - key = add_key_str_dict_element(plist, dict, "Request", "StartService", 1); - if (!key) { - xmlFreeDoc(plist); - return IPHONE_E_UNKNOWN_ERROR; - } - key = add_key_str_dict_element(plist, dict, "Service", service, 1); - if (!key) { - xmlFreeDoc(plist); - return IPHONE_E_UNKNOWN_ERROR; - } + dict = plist_new_dict(); + plist_add_sub_key_el(dict, "Request"); + plist_add_sub_string_el(dict, "StartService"); + plist_add_sub_key_el(dict, "Service"); + plist_add_sub_string_el(dict, service); + plist_to_xml(dict, &XML_content, &length); + + /* send to iPhone */ + ret = iphone_lckd_send(client, XML_content, length, &bytes); - xmlDocDumpMemory(plist, (xmlChar **) & XML_query, &length); + free(XML_content); + XML_content = NULL; + plist_free(dict); + dict = NULL; - ret = iphone_lckd_send(client, XML_query, length, &bytes); - free(XML_query); if (IPHONE_E_SUCCESS != ret) return ret; - ret = iphone_lckd_recv(client, &XML_query, &bytes); - xmlFreeDoc(plist); + ret = iphone_lckd_recv(client, &XML_content, &bytes); + if (IPHONE_E_SUCCESS != ret) return ret; + plist_from_xml(XML_content, bytes, &dict); + if (XML_content) + free(XML_content); + + if (!dict) + return IPHONE_E_PLIST_ERROR; + if (bytes <= 0) return IPHONE_E_NOT_ENOUGH_DATA; else { - plist = xmlReadMemory(XML_query, bytes, NULL, NULL, 0); - if (!plist) - return IPHONE_E_UNKNOWN_ERROR; - dict = xmlDocGetRootElement(plist); - if (!dict) - return IPHONE_E_UNKNOWN_ERROR; - for (dict = dict->children; dict; dict = dict->next) { - if (!xmlStrcmp(dict->name, "dict")) - break; - } + plist_t query_node = plist_find_node_by_string(dict, "StartService"); + plist_t result_key_node = plist_get_next_sibling(query_node); + plist_t result_value_node = plist_get_next_sibling(result_key_node); - if (!dict) - return IPHONE_E_UNKNOWN_ERROR; - dictionary = read_dict_element_strings(dict); + plist_t port_key_node = plist_find_node_by_key(dict, "Port"); + plist_t port_value_node = plist_get_next_sibling(port_key_node); - for (i = 0; dictionary[i]; i += 2) { - log_debug_msg("lockdownd_start_service() dictionary %s: %s\n", dictionary[i], dictionary[i + 1]); + plist_type port_value_type; + char *result_key = NULL; + char *result_value = NULL; + char *port_key = NULL; + uint64_t port_value = 0; - if (!xmlStrcmp(dictionary[i], "Port")) { - port_loc = atoi(dictionary[i + 1]); - log_debug_msg("lockdownd_start_service() atoi'd port: %i\n", port); - } + if (plist_get_node_type(result_key_node) == PLIST_KEY) { + plist_get_key_val(result_key_node, &result_key); + } + if (plist_get_node_type(result_value_node) == PLIST_STRING) { + plist_get_string_val(result_value_node, &result_value); + } + if (plist_get_node_type(port_key_node) == PLIST_KEY) { + plist_get_key_val(port_key_node, &port_key); + } + port_value_type = plist_get_node_type(port_value_node); + if (port_value_type == PLIST_UINT) { + plist_get_uint_val(port_value_node, &port_value); + } - if (!xmlStrcmp(dictionary[i], "Result")) { - if (!xmlStrcmp(dictionary[i + 1], "Success")) { - result = 1; - } - } + if (result_key && result_value && port_key && + port_value_type == PLIST_UINT && + !strcmp(result_key, "Result") && !strcmp(result_value, "Success") && !strcmp(port_key, "Port")) { + port_loc = port_value; + ret = IPHONE_E_SUCCESS; } log_debug_msg("lockdownd_start_service(): DATA RECEIVED:\n\n"); - log_debug_msg(XML_query); + log_debug_msg(XML_content); log_debug_msg("end data received by lockdownd_start_service()\n"); - free(XML_query); - xmlFreeDoc(plist); - free_dictionary(dictionary); - if (port && result) { + plist_free(dict); + dict = NULL; + if (port && ret == IPHONE_E_SUCCESS) { *port = port_loc; return IPHONE_E_SUCCESS; } else diff --git a/src/lockdown.h b/src/lockdown.h index c30a182..18fd38b 100644 --- a/src/lockdown.h +++ b/src/lockdown.h @@ -23,7 +23,6 @@ #define LOCKDOWND_H #include "usbmux.h" -#include "plist.h" #include #include @@ -43,14 +42,13 @@ char *lockdownd_generate_hostid(void); iphone_lckd_client_t new_lockdownd_client(iphone_device_t phone); iphone_error_t lockdownd_hello(iphone_lckd_client_t control); -iphone_error_t lockdownd_generic_get_value(iphone_lckd_client_t control, const char *req_key, const char *req_string, - char **value); -iphone_error_t lockdownd_get_device_public_key(iphone_lckd_client_t control, char **public_key); - -iphone_error_t lockdownd_gen_pair_cert(char *public_key_b64, char **device_cert_b64, char **host_cert_b64, - char **root_cert_b64); -iphone_error_t lockdownd_pair_device(iphone_lckd_client_t control, char *public_key, char *host_id); -void lockdownd_close(iphone_lckd_client_t control); +iphone_error_t lockdownd_generic_get_value(iphone_lckd_client_t control, const char *req_key, const char *req_string, gnutls_datum_t *value); + +iphone_error_t lockdownd_get_device_public_key(iphone_lckd_client_t control, gnutls_datum_t * public_key); + +iphone_error_t lockdownd_gen_pair_cert(gnutls_datum_t public_key, gnutls_datum_t *device_cert, gnutls_datum_t *host_cert, gnutls_datum_t *root_cert); +iphone_error_t lockdownd_pair_device(iphone_lckd_client_t control, char *uid, char *host_id); +iphone_error_t lockdownd_close(iphone_lckd_client_t control); // SSL functions diff --git a/src/userpref.c b/src/userpref.c index 5f227b0..3e5eb06 100644 --- a/src/userpref.c +++ b/src/userpref.c @@ -111,10 +111,10 @@ int is_device_known(char *uid) * @return 1 on success and 0 if no public key is given or if it has already * been marked as connected previously. */ -int store_device_public_key(char *uid, char *public_key) +int store_device_public_key(char *uid, gnutls_datum_t public_key) { - if (NULL == public_key || is_device_known(uid)) + if (NULL == public_key.data || is_device_known(uid)) return 0; /* ensure config directory exists */ @@ -124,15 +124,11 @@ int store_device_public_key(char *uid, char *public_key) gchar *device_file = g_strconcat(uid, ".pem", NULL); gchar *pem = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIPHONE_CONF_DIR, device_file, NULL); - /* decode public key for storing */ - gsize decoded_size; - gchar *data = g_base64_decode(public_key, &decoded_size); /* store file */ FILE *pFile = fopen(pem, "wb"); - fwrite(data, 1, decoded_size, pFile); + fwrite(public_key.data, 1, public_key.size, pFile); fclose(pFile); g_free(pem); - g_free(data); g_free(device_file); return 1; } diff --git a/src/userpref.h b/src/userpref.h index e7835d0..7e606eb 100644 --- a/src/userpref.h +++ b/src/userpref.h @@ -40,7 +40,7 @@ int is_device_known(char *uid); /** * @return 1 if everything went well. Returns 0 otherwise. */ -int store_device_public_key(char *uid, char *public_key); +int store_device_public_key(char *uid, gnutls_datum_t public_key); /** * @return 1 if everything went well. Returns 0 otherwise.