diff options
author | Matt Colyer | 2009-04-13 08:48:00 -0700 |
---|---|---|
committer | Matt Colyer | 2009-04-13 08:48:00 -0700 |
commit | 6671ca3d6de6a1fd27853e3b1ce7a81d568703f0 (patch) | |
tree | 735c5ace7ed57cd4e19f2fde423b22e6104eaa98 /src | |
parent | bd31783d7fde0b5bd101f4a3f97ca1aca2aa6fab (diff) | |
parent | 288929f45cb2641690879b52ec514097995cd41a (diff) | |
download | libimobiledevice-6671ca3d6de6a1fd27853e3b1ce7a81d568703f0.tar.gz libimobiledevice-6671ca3d6de6a1fd27853e3b1ce7a81d568703f0.tar.bz2 |
Merged in Jonathan's libplist libiphone. [#2 state:resolved]
Diffstat (limited to 'src')
-rw-r--r-- | src/AFC.c | 57 | ||||
-rw-r--r-- | src/AFC.h | 10 | ||||
-rw-r--r-- | src/Makefile.am | 14 | ||||
-rw-r--r-- | src/MobileSync.c | 299 | ||||
-rw-r--r-- | src/MobileSync.h | 39 | ||||
-rw-r--r-- | src/NotificationProxy.c | 91 | ||||
-rw-r--r-- | src/NotificationProxy.h | 1 | ||||
-rw-r--r-- | src/initconf.c | 185 | ||||
-rw-r--r-- | src/lockdown.c | 1007 | ||||
-rw-r--r-- | src/lockdown.h | 21 | ||||
-rw-r--r-- | src/plist.c | 245 | ||||
-rw-r--r-- | src/plist.h | 38 | ||||
-rw-r--r-- | src/usbmux.c | 3 | ||||
-rw-r--r-- | src/usbmux.h | 20 | ||||
-rw-r--r-- | src/userpref.c | 334 | ||||
-rw-r--r-- | src/userpref.h | 50 | ||||
-rw-r--r-- | src/utils.c | 25 | ||||
-rw-r--r-- | src/utils.h | 4 |
18 files changed, 1251 insertions, 1192 deletions
@@ -21,8 +21,7 @@ #include <stdio.h> #include "AFC.h" -#include "plist.h" -#include "utils.h" + // This is the maximum size an AFC data packet can be @@ -246,7 +245,7 @@ static int receive_AFC_data(iphone_afc_client_t client, char **dump_here) return retval; } - uint32 param1 = buffer[sizeof(AFCPacket)]; + uint32_t param1 = buffer[sizeof(AFCPacket)]; free(buffer); if (r_packet->operation == AFC_ERROR && !(client->afc_packet->operation == AFC_DELETE && param1 == 7)) { @@ -475,7 +474,7 @@ iphone_error_t iphone_afc_delete_file(iphone_afc_client_t client, const char *pa iphone_error_t iphone_afc_rename_file(iphone_afc_client_t client, const char *from, const char *to) { char *response = NULL; - char *send = (char *) malloc(sizeof(char) * (strlen(from) + strlen(to) + 1 + sizeof(uint32))); + char *send = (char *) malloc(sizeof(char) * (strlen(from) + strlen(to) + 1 + sizeof(uint32_t))); int bytes = 0; if (!client || !from || !to || !client->afc_packet || !client->connection) @@ -661,7 +660,7 @@ iphone_afc_open_file(iphone_afc_client_t client, const char *filename, iphone_afc_file_mode_t file_mode, iphone_afc_file_t * file) { iphone_afc_file_t file_loc = NULL; - uint32 ag = 0; + uint32_t ag = 0; int bytes = 0, length = 0; char *data = (char *) malloc(sizeof(char) * (8 + strlen(filename) + 1)); @@ -796,8 +795,8 @@ iphone_afc_write_file(iphone_afc_client_t client, iphone_afc_file_t file, { char *acknowledgement = NULL; const int MAXIMUM_WRITE_SIZE = 1 << 15; - uint32 zero = 0, current_count = 0, i = 0; - uint32 segments = (length / MAXIMUM_WRITE_SIZE); + uint32_t zero = 0, current_count = 0, i = 0; + uint32_t segments = (length / MAXIMUM_WRITE_SIZE); int bytes_loc = 0; char *out_buffer = NULL; @@ -815,8 +814,8 @@ iphone_afc_write_file(iphone_afc_client_t client, iphone_afc_file_t file, client->afc_packet->entire_length = client->afc_packet->this_length + MAXIMUM_WRITE_SIZE; client->afc_packet->operation = AFC_WRITE; out_buffer = (char *) malloc(sizeof(char) * client->afc_packet->entire_length - sizeof(AFCPacket)); - memcpy(out_buffer, (char *) &file->filehandle, sizeof(uint32)); - memcpy(out_buffer + 4, (char *) &zero, sizeof(uint32)); + memcpy(out_buffer, (char *) &file->filehandle, sizeof(uint32_t)); + memcpy(out_buffer + 4, (char *) &zero, sizeof(uint32_t)); memcpy(out_buffer + 8, data + current_count, MAXIMUM_WRITE_SIZE); bytes_loc = dispatch_AFC_packet(client, out_buffer, MAXIMUM_WRITE_SIZE + 8); if (bytes_loc < 0) { @@ -848,8 +847,8 @@ iphone_afc_write_file(iphone_afc_client_t client, iphone_afc_file_t file, client->afc_packet->entire_length = client->afc_packet->this_length + (length - current_count); client->afc_packet->operation = AFC_WRITE; out_buffer = (char *) malloc(sizeof(char) * client->afc_packet->entire_length - sizeof(AFCPacket)); - memcpy(out_buffer, (char *) &file->filehandle, sizeof(uint32)); - memcpy(out_buffer + 4, (char *) &zero, sizeof(uint32)); + memcpy(out_buffer, (char *) &file->filehandle, sizeof(uint32_t)); + memcpy(out_buffer + 4, (char *) &zero, sizeof(uint32_t)); memcpy(out_buffer + 8, data + current_count, (length - current_count)); bytes_loc = dispatch_AFC_packet(client, out_buffer, (length - current_count) + 8); free(out_buffer); @@ -884,7 +883,7 @@ iphone_error_t iphone_afc_close_file(iphone_afc_client_t client, iphone_afc_file if (!client || !file) return IPHONE_E_INVALID_ARG; char *buffer = malloc(sizeof(char) * 8); - uint32 zero = 0; + uint32_t zero = 0; int bytes = 0; afc_lock(client); @@ -892,8 +891,8 @@ iphone_error_t iphone_afc_close_file(iphone_afc_client_t client, iphone_afc_file log_debug_msg("afc_close_file: File handle %i\n", file->filehandle); // Send command - memcpy(buffer, &file->filehandle, sizeof(uint32)); - memcpy(buffer + sizeof(uint32), &zero, sizeof(zero)); + memcpy(buffer, &file->filehandle, sizeof(uint32_t)); + memcpy(buffer + sizeof(uint32_t), &zero, sizeof(zero)); client->afc_packet->operation = AFC_FILE_CLOSE; client->afc_packet->entire_length = client->afc_packet->this_length = 0; bytes = dispatch_AFC_packet(client, buffer, sizeof(char) * 8); @@ -939,7 +938,7 @@ iphone_error_t iphone_afc_lock_file(iphone_afc_client_t client, iphone_afc_file_ if (!client || !file) return IPHONE_E_INVALID_ARG; char *buffer = malloc(16); - uint32 zero = 0; + uint32_t zero = 0; int bytes = 0; uint64_t op = operation; @@ -948,8 +947,8 @@ iphone_error_t iphone_afc_lock_file(iphone_afc_client_t client, iphone_afc_file_ log_debug_msg("afc_lock_file: File handle %i\n", file->filehandle); // Send command - memcpy(buffer, &file->filehandle, sizeof(uint32)); - memcpy(buffer + sizeof(uint32), &zero, sizeof(zero)); + memcpy(buffer, &file->filehandle, sizeof(uint32_t)); + memcpy(buffer + sizeof(uint32_t), &zero, sizeof(zero)); memcpy(buffer + 8, &op, 8); client->afc_packet->operation = AFC_FILE_LOCK; @@ -986,7 +985,7 @@ iphone_error_t iphone_afc_lock_file(iphone_afc_client_t client, iphone_afc_file_ iphone_error_t iphone_afc_seek_file(iphone_afc_client_t client, iphone_afc_file_t file, int seekpos) { char *buffer = (char *) malloc(sizeof(char) * 24); - uint32 seekto = 0, zero = 0; + uint32_t seekto = 0, zero = 0; int bytes = 0; if (seekpos < 0) @@ -996,12 +995,12 @@ iphone_error_t iphone_afc_seek_file(iphone_afc_client_t client, iphone_afc_file_ // Send the command seekto = seekpos; - memcpy(buffer, &file->filehandle, sizeof(uint32)); // handle - memcpy(buffer + 4, &zero, sizeof(uint32)); // pad - memcpy(buffer + 8, &zero, sizeof(uint32)); // fromwhere - memcpy(buffer + 12, &zero, sizeof(uint32)); // pad - memcpy(buffer + 16, &seekto, sizeof(uint32)); // offset - memcpy(buffer + 20, &zero, sizeof(uint32)); // pad + memcpy(buffer, &file->filehandle, sizeof(uint32_t)); // handle + memcpy(buffer + 4, &zero, sizeof(uint32_t)); // pad + memcpy(buffer + 8, &zero, sizeof(uint32_t)); // fromwhere + memcpy(buffer + 12, &zero, sizeof(uint32_t)); // pad + memcpy(buffer + 16, &seekto, sizeof(uint32_t)); // offset + memcpy(buffer + 20, &zero, sizeof(uint32_t)); // pad client->afc_packet->operation = AFC_FILE_SEEK; client->afc_packet->this_length = client->afc_packet->entire_length = 0; bytes = dispatch_AFC_packet(client, buffer, 23); @@ -1041,14 +1040,14 @@ iphone_error_t iphone_afc_truncate_file(iphone_afc_client_t client, iphone_afc_f { char *buffer = (char *) malloc(sizeof(char) * 16); int bytes = 0; - uint32 zero = 0; + uint32_t zero = 0; afc_lock(client); // Send command - memcpy(buffer, &file->filehandle, sizeof(uint32)); // handle - memcpy(buffer + 4, &zero, sizeof(uint32)); // pad - memcpy(buffer + 8, &newsize, sizeof(uint32)); // newsize + memcpy(buffer, &file->filehandle, sizeof(uint32_t)); // handle + memcpy(buffer + 4, &zero, sizeof(uint32_t)); // pad + memcpy(buffer + 8, &newsize, sizeof(uint32_t)); // newsize memcpy(buffer + 12, &zero, 3); // pad client->afc_packet->operation = AFC_FILE_TRUNCATE; client->afc_packet->this_length = client->afc_packet->entire_length = 0; @@ -1121,7 +1120,7 @@ iphone_error_t iphone_afc_truncate(iphone_afc_client_t client, const char *path, } -uint32 iphone_afc_get_file_handle(iphone_afc_file_t file) +uint32_t iphone_afc_get_file_handle(iphone_afc_file_t file) { return file->filehandle; } @@ -29,12 +29,12 @@ #include <glib.h> typedef struct { - uint32 header1, header2; - uint32 entire_length, unknown1, this_length, unknown2, packet_num, unknown3, operation, unknown4; + uint32_t header1, header2; + uint32_t entire_length, unknown1, this_length, unknown2, packet_num, unknown3, operation, unknown4; } AFCPacket; typedef struct { - uint32 filehandle, unknown1, size, unknown2; + uint32_t filehandle, unknown1, size, unknown2; } AFCFilePacket; typedef struct __AFCToken { @@ -51,7 +51,7 @@ struct iphone_afc_client_int { }; struct iphone_afc_file_int { - uint32 filehandle, blocks, size, type; + uint32_t filehandle, blocks, size, type; }; @@ -87,4 +87,4 @@ enum { AFC_MAKE_LINK = 0x0000001C // MakeLink }; -uint32 iphone_afc_get_file_handle(iphone_afc_file_t file); +uint32_t iphone_afc_get_file_handle(iphone_afc_file_t file); diff --git a/src/Makefile.am b/src/Makefile.am index 76b15ec..a10254c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,15 +1,7 @@ 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) - -bin_PROGRAMS = libiphone-initconf - - -libiphone_initconf_SOURCES = initconf.c userpref.c lockdown.c plist.c usbmux.c iphone.c utils.c -libiphone_initconf_CFLAGS = $(libgthread2_CFLAGS) $(AM_CFLAGS) -libiphone_initconf_LDFLAGS = $(libgthread2_LIBS) $(AM_LDFLAGS) - +AM_CFLAGS = $(GLOBAL_CFLAGS) $(libusb_CFLAGS) $(libglib2_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(libgthread2_CFLAGS) $(libplist_CFLAGS) $(LFS_CFLAGS) +AM_LDFLAGS = $(libusb_LIBS) $(libglib2_LIBS) $(libgnutls_LIBS) $(libtasn1_LIBS) $(libgthread2_LIBS) $(libplist_LIBS) 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 MobileSync.c diff --git a/src/MobileSync.c b/src/MobileSync.c new file mode 100644 index 0000000..b16a51b --- /dev/null +++ b/src/MobileSync.c @@ -0,0 +1,299 @@ +/* + * MobileSync.c + * Contains functions for the built-in MobileSync client. + * + * Copyright (c) 2009 Jonathan Beck All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "MobileSync.h" +#include <plist/plist.h> +#include <string.h> + + +#define MSYNC_VERSION_INT1 100 +#define MSYNC_VERSION_INT2 100 + +iphone_error_t iphone_msync_new_client(iphone_device_t device, int src_port, int dst_port, + iphone_msync_client_t * client) +{ + if (!device || src_port == 0 || dst_port == 0 || !client || *client) + return IPHONE_E_INVALID_ARG; + + iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; + + iphone_msync_client_t client_loc = (iphone_msync_client_t) malloc(sizeof(struct iphone_msync_client_int)); + + // Attempt connection + client_loc->connection = NULL; + ret = iphone_mux_new_client(device, src_port, dst_port, &client_loc->connection); + if (IPHONE_E_SUCCESS != ret || !client_loc->connection) { + free(client_loc); + return ret; + } + //perform handshake + plist_t array = NULL; + + //first receive version + ret = iphone_msync_recv(client_loc, &array); + + plist_t msg_node = plist_find_node_by_string(array, "DLMessageVersionExchange"); + plist_t ver_1 = plist_get_next_sibling(msg_node); + plist_t ver_2 = plist_get_next_sibling(ver_1); + + plist_type ver_1_type = plist_get_node_type(ver_1); + plist_type ver_2_type = plist_get_node_type(ver_2); + + if (PLIST_UINT == ver_1_type && PLIST_UINT == ver_2_type) { + + uint64_t ver_1_val = 0; + uint64_t ver_2_val = 0; + + plist_get_uint_val(ver_1, &ver_1_val); + plist_get_uint_val(ver_2, &ver_2_val); + + plist_free(array); + array = NULL; + + if (ver_1_type == PLIST_UINT && ver_2_type == PLIST_UINT && ver_1_val == MSYNC_VERSION_INT1 + && ver_2_val == MSYNC_VERSION_INT2) { + + array = plist_new_array(); + plist_add_sub_string_el(array, "DLMessageVersionExchange"); + plist_add_sub_string_el(array, "DLVersionsOk"); + + ret = iphone_msync_send(client_loc, array); + + plist_free(array); + array = NULL; + + ret = iphone_msync_recv(client_loc, &array); + plist_t rep_node = plist_find_node_by_string(array, "DLMessageDeviceReady"); + + if (rep_node) { + ret = IPHONE_E_SUCCESS; + *client = client_loc; + } + plist_free(array); + array = NULL; + + } + } + + if (IPHONE_E_SUCCESS != ret) + iphone_msync_free_client(client_loc); + + return ret; +} + +static void iphone_msync_stop_session(iphone_msync_client_t client) +{ + if (!client) + return; + + plist_t array = plist_new_array(); + plist_add_sub_string_el(array, "DLMessageDisconnect"); + plist_add_sub_string_el(array, "All done, thanks for the memories"); + + iphone_msync_send(client, array); + plist_free(array); + array = NULL; +} + +iphone_error_t iphone_msync_free_client(iphone_msync_client_t client) +{ + if (!client) + return IPHONE_E_INVALID_ARG; + + iphone_msync_stop_session(client); + return iphone_mux_free_client(client->connection); +} + +/** Polls the iPhone for MobileSync data. + * + * @param client The MobileSync client + * @param dump_data The pointer to the location of the buffer in which to store + * the received data + * @param recv_byhtes The number of bytes received + * + * @return an error code + */ +iphone_error_t iphone_msync_recv(iphone_msync_client_t client, plist_t * plist) +{ + if (!client || !plist || (plist && *plist)) + return IPHONE_E_INVALID_ARG; + iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; + char *receive; + uint32_t datalen = 0, bytes = 0; + + ret = iphone_mux_recv(client->connection, (char *) &datalen, sizeof(datalen), &bytes); + datalen = ntohl(datalen); + + receive = (char *) malloc(sizeof(char) * datalen); + ret = iphone_mux_recv(client->connection, receive, datalen, &bytes); + + plist_from_bin(receive, bytes, plist); + + char *XMLContent = NULL; + uint32_t length = 0; + plist_to_xml(*plist, &XMLContent, &length); + log_dbg_msg(DBGMASK_MOBILESYNC, "Recv msg :\nsize : %i\nbuffer :\n%s\n", length, XMLContent); + free(XMLContent); + + return ret; +} + +/** Sends MobileSync data to the iPhone + * + * @note This function is low-level and should only be used if you need to send + * a new type of message. + * + * @param client The MobileSync client + * @param raw_data The null terminated string buffer to send + * @param length The length of data to send + * @param sent_bytes The number of bytes sent + * + * @return an error code + */ +iphone_error_t iphone_msync_send(iphone_msync_client_t client, plist_t plist) +{ + if (!client || !plist) + return IPHONE_E_INVALID_ARG; + + char *XMLContent = NULL; + uint32_t length = 0; + plist_to_xml(plist, &XMLContent, &length); + log_dbg_msg(DBGMASK_MOBILESYNC, "Send msg :\nsize : %i\nbuffer :\n%s\n", length, XMLContent); + free(XMLContent); + + char *content = NULL; + length = 0; + + plist_to_bin(plist, &content, &length); + + char *real_query; + int bytes; + iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; + + real_query = (char *) malloc(sizeof(char) * (length + 4)); + length = htonl(length); + memcpy(real_query, &length, sizeof(length)); + memcpy(real_query + 4, content, ntohl(length)); + + ret = iphone_mux_send(client->connection, real_query, ntohl(length) + sizeof(length), &bytes); + free(real_query); + return ret; +} + +iphone_error_t iphone_msync_get_all_contacts(iphone_msync_client_t client) +{ + if (!client) + return IPHONE_E_INVALID_ARG; + + iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; + plist_t array = NULL; + + array = plist_new_array(); + plist_add_sub_string_el(array, "SDMessageSyncDataClassWithDevice"); + plist_add_sub_string_el(array, "com.apple.Contacts"); + plist_add_sub_string_el(array, "---"); + plist_add_sub_string_el(array, "2009-01-09 18:03:58 +0100"); + plist_add_sub_uint_el(array, 106); + plist_add_sub_string_el(array, "___EmptyParameterString___"); + + ret = iphone_msync_send(client, array); + plist_free(array); + array = NULL; + + ret = iphone_msync_recv(client, &array); + + plist_t rep_node = plist_find_node_by_string(array, "SDSyncTypeSlow"); + + if (!rep_node) + return ret; + + plist_free(array); + array = NULL; + + array = plist_new_array(); + plist_add_sub_string_el(array, "SDMessageGetAllRecordsFromDevice"); + plist_add_sub_string_el(array, "com.apple.Contacts"); + + + ret = iphone_msync_send(client, array); + plist_free(array); + array = NULL; + + ret = iphone_msync_recv(client, &array); + + plist_t contact_node; + plist_t switch_node; + + contact_node = plist_find_node_by_string(array, "com.apple.Contacts"); + switch_node = plist_find_node_by_string(array, "SDMessageDeviceReadyToReceiveChanges"); + + while (NULL == switch_node) { + + plist_free(array); + array = NULL; + + array = plist_new_array(); + plist_add_sub_string_el(array, "SDMessageAcknowledgeChangesFromDevice"); + plist_add_sub_string_el(array, "com.apple.Contacts"); + + ret = iphone_msync_send(client, array); + plist_free(array); + array = NULL; + + ret = iphone_msync_recv(client, &array); + + contact_node = plist_find_node_by_string(array, "com.apple.Contacts"); + switch_node = plist_find_node_by_string(array, "SDMessageDeviceReadyToReceiveChanges"); + } + + array = plist_new_array(); + plist_add_sub_string_el(array, "DLMessagePing"); + plist_add_sub_string_el(array, "Preparing to get changes for device"); + + ret = iphone_msync_send(client, array); + plist_free(array); + array = NULL; + + array = plist_new_array(); + plist_add_sub_string_el(array, "SDMessageProcessChanges"); + plist_add_sub_string_el(array, "com.apple.Contacts"); + plist_add_sub_node(array, plist_new_dict()); + plist_add_sub_bool_el(array, 0); + plist_t dict = plist_new_dict(); + plist_add_sub_node(array, dict); + plist_add_sub_key_el(dict, "SyncDeviceLinkEntityNamesKey"); + plist_t array2 = plist_new_array(); + plist_add_sub_string_el(array2, "com.apple.contacts.Contact"); + plist_add_sub_string_el(array2, "com.apple.contacts.Group"); + plist_add_sub_key_el(dict, "SyncDeviceLinkAllRecordsOfPulledEntityTypeSentKey"); + plist_add_sub_bool_el(dict, 0); + + ret = iphone_msync_send(client, array); + plist_free(array); + array = NULL; + + ret = iphone_msync_recv(client, &array); + plist_free(array); + array = NULL; + + + return ret; +} diff --git a/src/MobileSync.h b/src/MobileSync.h new file mode 100644 index 0000000..7655b59 --- /dev/null +++ b/src/MobileSync.h @@ -0,0 +1,39 @@ +/* + * MobileSync.h + * Definitions for the built-in MobileSync client + * + * Copyright (c) 2009 Jonathan Beck All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef MOBILESYNC_H +#define MOBILESYNC_H + +#include "usbmux.h" +#include "iphone.h" +#include "utils.h" + +#include <plist/plist.h> + + + +struct iphone_msync_client_int { + iphone_umux_client_t connection; +}; + + +iphone_error_t iphone_msync_get_all_contacts(iphone_msync_client_t client); + +#endif diff --git a/src/NotificationProxy.c b/src/NotificationProxy.c index defbc4e..bf837bf 100644 --- a/src/NotificationProxy.c +++ b/src/NotificationProxy.c @@ -21,8 +21,8 @@ #include <string.h> #include <stdio.h> +#include <plist/plist.h> #include "NotificationProxy.h" -#include "plist.h" #include "utils.h" /** Locks an NP client, done for thread safety stuff. @@ -104,26 +104,26 @@ 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; - int bytes; + char *XML_content = NULL; + uint32_t length = 0; + int bytes = 0; iphone_error_t ret; unsigned char sndbuf[4096]; int sndlen = 0; - int nlen; + int nlen = 0; + plist_t dict = NULL; if (!client || !notification) { return IPHONE_E_INVALID_ARG; } 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); @@ -132,13 +132,15 @@ iphone_error_t iphone_np_post_notification(iphone_np_client_t client, const char memcpy(sndbuf + sndlen, XML_content, length); sndlen += length; - xmlFree(XML_content); - xmlFreeDoc(plist); + plist_free(dict); + dict = NULL; + free(XML_content); + XML_content = NULL; - 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); @@ -148,9 +150,10 @@ iphone_error_t iphone_np_post_notification(iphone_np_client_t client, const char memcpy(sndbuf + sndlen, XML_content, length); sndlen += length; - xmlFree(XML_content); - xmlFreeDoc(plist); - plist = NULL; + plist_free(dict); + dict = NULL; + free(XML_content); + XML_content = NULL; log_debug_buffer(sndbuf, sndlen); @@ -181,17 +184,16 @@ 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; - char *XML_content; - uint32_t length; - int bytes; + plist_t dict = NULL; + char *XML_content = NULL; + uint32_t length = 0; + int bytes = 0; iphone_error_t ret; unsigned char sndbuf[4096]; int sndlen = 0; - int nlen; + int nlen = 0; int i = 0; - char *notifications[10] = { + const char *notifications[10] = { "com.apple.itunes-client.syncCancelRequest", "com.apple.itunes-client.syncSuspendRequest", "com.apple.itunes-client.syncResumeRequest", @@ -212,11 +214,13 @@ 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); @@ -224,14 +228,16 @@ 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); + plist_free(dict); + dict = NULL; + free(XML_content); + XML_content = NULL; } - 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); @@ -241,9 +247,10 @@ 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); - plist = NULL; + plist_free(dict); + dict = NULL; + free(XML_content); + XML_content = NULL; log_debug_buffer(sndbuf, sndlen); diff --git a/src/NotificationProxy.h b/src/NotificationProxy.h index b2fa3d9..7b4b48d 100644 --- a/src/NotificationProxy.h +++ b/src/NotificationProxy.h @@ -18,6 +18,7 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libiphone/libiphone.h" #include "usbmux.h" #include "iphone.h" diff --git a/src/initconf.c b/src/initconf.c deleted file mode 100644 index 205c97a..0000000 --- a/src/initconf.c +++ /dev/null @@ -1,185 +0,0 @@ -/* - * userpref.c - * contains methods to access user specific certificates IDs and more. - * - * Copyright (c) 2008 Jonathan Beck All Rights Reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <gnutls/gnutls.h> -#include <gnutls/x509.h> -#include <glib.h> - -#include "libiphone/libiphone.h" -#include "userpref.h" -#include "lockdown.h" -#include "utils.h" - -/** Generates a 2048 byte key, split into a function so that it can be run in a - * thread. - * - * @param key The pointer to the desired location of the new key. - */ -static void generate_key(gpointer key) -{ - gnutls_x509_privkey_generate(*((gnutls_x509_privkey_t *) key), GNUTLS_PK_RSA, 2048, 0); - g_thread_exit(0); -} - -/** Simple function that generates a spinner until the mutex is released. - */ -static void progress_bar(gpointer mutex) -{ - const char *spinner = "|/-\\|/-\\"; - int i = 0; - - while (!g_static_mutex_trylock((GStaticMutex *) mutex)) { - usleep(500000); - printf("Generating key... %c\r", spinner[i++]); - fflush(stdout); - if (i > 8) - i = 0; - } - printf("Generating key... done\n"); - g_thread_exit(0); -} - -int main(int argc, char *argv[]) -{ - GThread *progress_thread, *key_thread; - GError *err; - static GStaticMutex mutex = G_STATIC_MUTEX_INIT; - char *host_id = NULL; - gnutls_x509_privkey_t root_privkey; - gnutls_x509_privkey_t host_privkey; - gnutls_x509_crt_t root_cert; - gnutls_x509_crt_t host_cert; - - iphone_set_debug(1); - - // Create the thread - if (!g_thread_supported()) { - g_thread_init(NULL); - } - gnutls_global_init(); - - printf("This program generates keys required to connect with the iPhone\n"); - printf("It only needs to be run ONCE.\n\n"); - printf("Additionally it may take several minutes to run, please be patient.\n\n"); - - - gnutls_x509_privkey_init(&root_privkey); - gnutls_x509_privkey_init(&host_privkey); - - gnutls_x509_crt_init(&root_cert); - gnutls_x509_crt_init(&host_cert); - - /* generate HostID */ - host_id = lockdownd_generate_hostid(); - - /* generate root key */ - g_static_mutex_lock(&mutex); - if ((key_thread = g_thread_create((GThreadFunc) generate_key, &root_privkey, TRUE, &err)) == NULL) { - printf("Thread create failed: %s!!\n", err->message); - g_error_free(err); - } - if ((progress_thread = g_thread_create((GThreadFunc) progress_bar, &mutex, TRUE, &err)) == NULL) { - printf("Thread create failed: %s!!\n", err->message); - g_error_free(err); - } - g_thread_join(key_thread); - g_static_mutex_unlock(&mutex); - g_thread_join(progress_thread); - - /* generate host key */ - g_static_mutex_init(&mutex); - g_static_mutex_lock(&mutex); - if ((key_thread = g_thread_create((GThreadFunc) generate_key, &host_privkey, TRUE, &err)) == NULL) { - printf("Thread create failed: %s!!\n", err->message); - g_error_free(err); - } - if ((progress_thread = g_thread_create((GThreadFunc) progress_bar, &mutex, TRUE, &err)) == NULL) { - printf("Thread create failed: %s!!\n", err->message); - g_error_free(err); - } - g_thread_join(key_thread); - g_static_mutex_unlock(&mutex); - g_thread_join(progress_thread); - - /* generate certificates */ - gnutls_x509_crt_set_key(root_cert, root_privkey); - gnutls_x509_crt_set_serial(root_cert, "\x00", 1); - gnutls_x509_crt_set_version(root_cert, 3); - gnutls_x509_crt_set_ca_status(root_cert, 1); - gnutls_x509_crt_set_activation_time(root_cert, time(NULL)); - gnutls_x509_crt_set_expiration_time(root_cert, time(NULL) + (60 * 60 * 24 * 365 * 10)); - gnutls_x509_crt_sign(root_cert, root_cert, root_privkey); - - - gnutls_x509_crt_set_key(host_cert, host_privkey); - gnutls_x509_crt_set_serial(host_cert, "\x00", 1); - gnutls_x509_crt_set_version(host_cert, 3); - gnutls_x509_crt_set_ca_status(host_cert, 0); - gnutls_x509_crt_set_key_usage(host_cert, GNUTLS_KEY_KEY_ENCIPHERMENT | GNUTLS_KEY_DIGITAL_SIGNATURE); - gnutls_x509_crt_set_activation_time(host_cert, time(NULL)); - gnutls_x509_crt_set_expiration_time(host_cert, time(NULL) + (60 * 60 * 24 * 365 * 10)); - gnutls_x509_crt_sign(host_cert, root_cert, root_privkey); - - - /* export to PEM format */ - gnutls_datum_t root_key_pem = { NULL, 0 }; - gnutls_datum_t host_key_pem = { NULL, 0 }; - - gnutls_x509_privkey_export(root_privkey, GNUTLS_X509_FMT_PEM, NULL, &root_key_pem.size); - gnutls_x509_privkey_export(host_privkey, GNUTLS_X509_FMT_PEM, NULL, &host_key_pem.size); - - root_key_pem.data = gnutls_malloc(root_key_pem.size); - host_key_pem.data = gnutls_malloc(host_key_pem.size); - - gnutls_x509_privkey_export(root_privkey, GNUTLS_X509_FMT_PEM, root_key_pem.data, &root_key_pem.size); - gnutls_x509_privkey_export(host_privkey, GNUTLS_X509_FMT_PEM, host_key_pem.data, &host_key_pem.size); - - gnutls_datum_t root_cert_pem = { NULL, 0 }; - gnutls_datum_t host_cert_pem = { NULL, 0 }; - - gnutls_x509_crt_export(root_cert, GNUTLS_X509_FMT_PEM, NULL, &root_cert_pem.size); - gnutls_x509_crt_export(host_cert, GNUTLS_X509_FMT_PEM, NULL, &host_cert_pem.size); - - root_cert_pem.data = gnutls_malloc(root_cert_pem.size); - host_cert_pem.data = gnutls_malloc(host_cert_pem.size); - - printf("Generating root certificate..."); - gnutls_x509_crt_export(root_cert, GNUTLS_X509_FMT_PEM, root_cert_pem.data, &root_cert_pem.size); - printf("done\n"); - - printf("Generating host certificate..."); - gnutls_x509_crt_export(host_cert, GNUTLS_X509_FMT_PEM, host_cert_pem.data, &host_cert_pem.size); - printf("done\n"); - - - /* store values in config file */ - init_config_file(host_id, &root_key_pem, &host_key_pem, &root_cert_pem, &host_cert_pem); - - gnutls_free(root_key_pem.data); - gnutls_free(host_key_pem.data); - gnutls_free(root_cert_pem.data); - gnutls_free(host_cert_pem.data); - - return 0; -} diff --git a/src/lockdown.c b/src/lockdown.c index 73a8bbc..e720b29 100644 --- a/src/lockdown.c +++ b/src/lockdown.c @@ -1,22 +1,22 @@ /* * lockdown.c * libiphone built-in lockdownd client - * + * * Copyright (c) 2008 Zach C. All Rights Reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "usbmux.h" @@ -31,6 +31,9 @@ #include <libtasn1.h> #include <gnutls/x509.h> +#include <plist/plist.h> + + const ASN1_ARRAY_TYPE pkcs1_asn1_tab[] = { {"PKCS1", 536872976, 0}, {0, 1073741836, 0}, @@ -40,35 +43,6 @@ const ASN1_ARRAY_TYPE pkcs1_asn1_tab[] = { {0, 0, 0} }; -static int get_rand(int min, int max) -{ - int retval = (rand() % (max - min)) + min; - return retval; -} - -/** Generates a valid HostID (which is actually a UUID). - * - * @param A null terminated string containing a valid HostID. - */ -char *lockdownd_generate_hostid(void) -{ - char *hostid = (char *) malloc(sizeof(char) * 37); // HostID's are just UUID's, and UUID's are 36 characters long - const char *chars = "ABCDEF0123456789"; - srand(time(NULL)); - int i = 0; - - for (i = 0; i < 36; i++) { - if (i == 8 || i == 13 || i == 18 || i == 23) { - hostid[i] = '-'; - continue; - } else { - hostid[i] = chars[get_rand(0, 16)]; - } - } - hostid[36] = '\0'; // make it a real string - return hostid; -} - /** Creates a lockdownd client for the give iPhone. * * @param phone The iPhone to create a lockdownd client for @@ -93,69 +67,68 @@ iphone_lckd_client_t new_lockdownd_client(iphone_device_t phone) /** * Closes the lockdownd communication session, by sending - * the StopSession Request to the device. + * the StopSession Request to the device. * * @param control The lockdown client */ static void 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; + 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_dbg_msg(DBGMASK_LOCKDOWND, "iphone_lckd_stop_session() called\n"); - xmlDocDumpMemory(plist, (xmlChar **) & XML_content, &length); - ret = iphone_lckd_send(control, XML_content, length, &bytes); + ret = iphone_lckd_send(control, dict); - xmlFree(XML_content); - xmlFreeDoc(plist); - plist = NULL; - ret = iphone_lckd_recv(control, &XML_content, &bytes); + plist_free(dict); + dict = NULL; + + ret = iphone_lckd_recv(control, &dict); - plist = xmlReadMemory(XML_content, bytes, NULL, NULL, 0); - if (!plist) { - log_debug_msg("lockdownd_stop_session(): IPHONE_E_PLIST_ERROR\n"); - return; //IPHONE_E_PLIST_ERROR; - } - dict = xmlDocGetRootElement(plist); - for (dict = dict->children; dict; dict = dict->next) { - if (!xmlStrcmp(dict->name, "dict")) - break; - } if (!dict) { - log_debug_msg("lockdownd_stop_session(): IPHONE_E_DICT_ERROR\n"); - return; //IPHONE_E_DICT_ERROR; + log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_stop_session(): IPHONE_E_PLIST_ERROR\n"); + return; // IPHONE_E_PLIST_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_stop_session(): success\n"); + 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); + + plist_type result_type = plist_get_node_type(result_node); + plist_type value_type = plist_get_node_type(value_node); + + if (result_type == PLIST_KEY && value_type == PLIST_STRING) { + + char *result_value = NULL; + char *value_value = NULL; + + plist_get_key_val(result_node, &result_value); + plist_get_string_val(value_node, &value_value); + + if (!strcmp(result_value, "Result") && !strcmp(value_value, "Success")) { + log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_stop_session(): success\n"); ret = IPHONE_E_SUCCESS; - break; } + free(result_value); + free(value_value); } + plist_free(dict); + dict = NULL; - free_dictionary(dictionary); - return; //ret; + return; // ret; } /** * Shuts down the SSL session by first calling iphone_lckd_stop_session - * to cleanly close the lockdownd communication session, and then + * to cleanly close the lockdownd communication session, and then * performing a close notify, which is done by "gnutls_bye". * * @param client The lockdown client @@ -163,14 +136,14 @@ static void iphone_lckd_stop_session(iphone_lckd_client_t control) static void iphone_lckd_stop_SSL_session(iphone_lckd_client_t client) { if (!client) { - log_debug_msg("lockdownd_stop_SSL_session(): invalid argument!\n"); + log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_stop_SSL_session(): invalid argument!\n"); return; } if (client->in_SSL) { - log_debug_msg("Stopping SSL Session\n"); + log_dbg_msg(DBGMASK_LOCKDOWND, "Stopping SSL Session\n"); iphone_lckd_stop_session(client); - log_debug_msg("Sending SSL close notify\n"); + log_dbg_msg(DBGMASK_LOCKDOWND, "Sending SSL close notify\n"); gnutls_bye(*client->ssl_session, GNUTLS_SHUT_RDWR); } if (client->ssl_session) { @@ -215,13 +188,13 @@ iphone_error_t iphone_lckd_free_client(iphone_lckd_client_t client) * * @return The number of bytes received */ -iphone_error_t iphone_lckd_recv(iphone_lckd_client_t client, char **dump_data, uint32_t * recv_bytes) +iphone_error_t iphone_lckd_recv(iphone_lckd_client_t client, plist_t * plist) { - if (!client || !dump_data || !recv_bytes) + if (!client || !plist || (plist && *plist)) return IPHONE_E_INVALID_ARG; iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; char *receive; - uint32 datalen = 0, bytes = 0; + uint32_t datalen = 0, bytes = 0; if (!client->in_SSL) ret = iphone_mux_recv(client->connection, (char *) &datalen, sizeof(datalen), &bytes); @@ -240,36 +213,52 @@ iphone_error_t iphone_lckd_recv(iphone_lckd_client_t client, char **dump_data, u if (bytes > 0) ret = IPHONE_E_SUCCESS; } - *dump_data = receive; - *recv_bytes = bytes; + + if (bytes <= 0) { + free(receive); + return IPHONE_E_NOT_ENOUGH_DATA; + } + + log_dbg_msg(DBGMASK_LOCKDOWND, "Recv msg :\nsize : %i\nbuffer :\n%s\n", bytes, receive); + plist_from_xml(receive, bytes, plist); + free(receive); + + if (!*plist) + ret = IPHONE_E_PLIST_ERROR; + return ret; } /** Sends lockdownd data to the iPhone - * + * * @note This function is low-level and should only be used if you need to send * a new type of message. * - * @param control The lockdownd client - * @param raw_data The null terminated string buffer to send - * @param length The length of data to send + * @param client The lockdownd client + * @param plist The plist to send * - * @return The number of bytes sent + * @return an error code (IPHONE_E_SUCCESS on success) */ -iphone_error_t iphone_lckd_send(iphone_lckd_client_t client, char *raw_data, uint32_t length, uint32_t * sent_bytes) +iphone_error_t iphone_lckd_send(iphone_lckd_client_t client, plist_t plist) { - if (!client || !raw_data || length == 0 || !sent_bytes) + if (!client || !plist) return IPHONE_E_INVALID_ARG; char *real_query; int bytes; + char *XMLContent = NULL; + uint32_t length = 0; iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; + plist_to_xml(plist, &XMLContent, &length); + log_dbg_msg(DBGMASK_LOCKDOWND, "Send msg :\nsize : %i\nbuffer :\n%s\n", length, XMLContent); + + real_query = (char *) malloc(sizeof(char) * (length + 4)); length = htonl(length); memcpy(real_query, &length, sizeof(length)); - memcpy(real_query + 4, raw_data, ntohl(length)); - log_debug_msg("lockdownd_send(): made the query, sending it along\n"); - dump_debug_buffer("grpkt", real_query, ntohl(length) + 4); + memcpy(real_query + 4, XMLContent, ntohl(length)); + free(XMLContent); + log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_send(): made the query, sending it along\n"); if (!client->in_SSL) ret = iphone_mux_send(client->connection, real_query, ntohl(length) + sizeof(length), &bytes); @@ -277,14 +266,14 @@ iphone_error_t iphone_lckd_send(iphone_lckd_client_t client, char *raw_data, uin gnutls_record_send(*client->ssl_session, real_query, ntohl(length) + sizeof(length)); ret = IPHONE_E_SUCCESS; } - log_debug_msg("lockdownd_send(): sent it!\n"); + log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_send(): sent it!\n"); free(real_query); - *sent_bytes = bytes; + return ret; } /** Initiates the handshake for the lockdown session. Part of the lockdownd handshake. - * + * * @note You most likely want lockdownd_init unless you are doing something special. * * @param control The lockdownd client @@ -295,49 +284,50 @@ 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; + iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; - 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; + plist_t dict = plist_new_dict(); + plist_add_sub_key_el(dict, "Request"); + plist_add_sub_string_el(dict, "QueryType"); - xmlDocDumpMemory(plist, (xmlChar **) & XML_content, &length); - ret = iphone_lckd_send(control, XML_content, length, &bytes); + log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_hello() called\n"); + ret = iphone_lckd_send(control, dict); - xmlFree(XML_content); - xmlFreeDoc(plist); - plist = NULL; - ret = iphone_lckd_recv(control, &XML_content, &bytes); + plist_free(dict); + dict = NULL; - plist = xmlReadMemory(XML_content, bytes, NULL, NULL, 0); - if (!plist) - return IPHONE_E_PLIST_ERROR; - dict = xmlDocGetRootElement(plist); - for (dict = dict->children; dict; dict = dict->next) { - if (!xmlStrcmp(dict->name, "dict")) - break; - } - 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_lckd_recv(control, &dict); + + if (IPHONE_E_SUCCESS != ret) + return ret; + + 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); + + plist_type result_type = plist_get_node_type(result_node); + plist_type value_type = plist_get_node_type(value_node); + + if (result_type == PLIST_KEY && value_type == PLIST_STRING) { + + char *result_value = NULL; + char *value_value = NULL; + + plist_get_key_val(result_node, &result_value); + plist_get_string_val(value_node, &value_value); + + if (!strcmp(result_value, "Result") && !strcmp(value_value, "Success")) { + log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_hello(): success\n"); ret = IPHONE_E_SUCCESS; - break; } + free(result_value); + free(value_value); } - free_dictionary(dictionary); + plist_free(dict); + dict = NULL; + return ret; } @@ -350,73 +340,100 @@ 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) + 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; - char *XML_content = NULL; - uint32 length = 0; + + plist_t dict = NULL; 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"); /* send to iPhone */ - ret = iphone_lckd_send(control, XML_content, length, &bytes); + ret = iphone_lckd_send(control, dict); - xmlFree(XML_content); - xmlFreeDoc(plist); - plist = NULL; + plist_free(dict); + dict = NULL; if (ret != IPHONE_E_SUCCESS) return ret; /* Now get iPhone's answer */ - ret = iphone_lckd_recv(control, &XML_content, &bytes); + ret = iphone_lckd_recv(control, &dict); if (ret != IPHONE_E_SUCCESS) return ret; - plist = xmlReadMemory(XML_content, bytes, NULL, NULL, 0); - if (!plist) - return IPHONE_E_PLIST_ERROR; - dict = xmlDocGetRootElement(plist); - for (dict = dict->children; dict; dict = dict->next) { - if (!xmlStrcmp(dict->name, "dict")) - break; - } - if (!dict) - return IPHONE_E_DICT_ERROR; + 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); - /* Parse xml to check success and to find public key */ - dictionary = read_dict_element_strings(dict); - xmlFreeDoc(plist); - free(XML_content); + plist_type result_key_type = plist_get_node_type(result_key_node); + plist_type result_value_type = plist_get_node_type(result_value_node); - 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_key_type == PLIST_KEY && result_value_type == PLIST_STRING) { + + char *result_key = NULL; + char *result_value = NULL; + ret = IPHONE_E_DICT_ERROR; + + plist_get_key_val(result_key_node, &result_key); + plist_get_string_val(result_value_node, &result_value); + + if (!strcmp(result_key, "Result") && !strcmp(result_value, "Success")) { + log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_generic_get_value(): success\n"); + ret = IPHONE_E_SUCCESS; } + free(result_key); + free(result_value); + } + if (ret != IPHONE_E_SUCCESS) { + return ret; } - if (dictionary) { - free_dictionary(dictionary); - dictionary = NULL; + plist_t value_key_node = plist_find_node_by_key(dict, "Value");//plist_get_next_sibling(result_value_node); + plist_t value_value_node = plist_get_next_sibling(value_key_node); + + plist_type value_key_type = plist_get_node_type(value_key_node); + + if (value_key_type == PLIST_KEY) { + + char *result_key = NULL; + plist_get_key_val(value_key_node, &result_key); + + if (!strcmp(result_key, "Value")) { + log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_generic_get_value(): success\n"); + + plist_type value_value_type = plist_get_node_type(value_value_node); + if (PLIST_STRING == value_value_type) { + char *value_value = NULL; + plist_get_string_val(value_value_node, &value_value); + + value->data = value_value; + value->size = strlen(value_value); + ret = IPHONE_E_SUCCESS; + } + + if (PLIST_DATA == value_value_type) { + char *value_value = NULL; + uint64_t size = 0; + plist_get_data_val(value_value_node, &value_value, &size); + + value->data = value_value; + value->size = size; + ret = IPHONE_E_SUCCESS; + } + } + free(result_key); } - if (success) - ret = IPHONE_E_SUCCESS; + + plist_free(dict); return ret; } @@ -428,7 +445,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 ret = lockdownd_generic_get_value(control, "Key", "UniqueDeviceID", &temp); + *uid = temp.data; + return ret; } /** Askes for the device's public key. Part of the lockdownd handshake. @@ -437,7 +457,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); } @@ -472,6 +492,7 @@ iphone_error_t iphone_lckd_new_client(iphone_device_t device, iphone_lckd_client if (IPHONE_E_SUCCESS != ret) { log_debug_msg("Device refused to send uid.\n"); } + log_debug_msg("Device uid: %s\n", uid); host_id = get_host_id(); if (IPHONE_E_SUCCESS == ret && !host_id) { @@ -487,19 +508,22 @@ iphone_error_t iphone_lckd_new_client(iphone_device_t device, iphone_lckd_client uid = NULL; } - ret = lockdownd_start_SSL_session(client_loc, host_id); - if (IPHONE_E_SUCCESS != ret) { - ret = IPHONE_E_SSL_ERROR; - log_debug_msg("SSL Session opening failed.\n"); - } + if (IPHONE_E_SUCCESS == ret) { + ret = lockdownd_start_SSL_session(client_loc, host_id); + if (IPHONE_E_SUCCESS != ret) { + ret = IPHONE_E_SSL_ERROR; + log_debug_msg("SSL Session opening failed.\n"); + } + + if (host_id) { + free(host_id); + host_id = NULL; + } - if (host_id) { - free(host_id); - host_id = NULL; + if (IPHONE_E_SUCCESS == ret) + *client = client_loc; } - if (IPHONE_E_SUCCESS == ret) - *client = client_loc; return ret; } @@ -513,107 +537,92 @@ 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; - char *XML_content = NULL; - uint32 length = 0; - - char *device_cert_b64 = NULL; - char *host_cert_b64 = NULL; - char *root_cert_b64 = NULL; - char *public_key_b64 = NULL; - - ret = lockdownd_get_device_public_key(control, &public_key_b64); + plist_t dict = NULL; + plist_t dict_record = 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); if (ret != IPHONE_E_SUCCESS) { log_debug_msg("Device refused to send public key.\n"); return ret; } + log_debug_msg("device public key :\n %s.\n", public_key.data); - 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); - - xmlDocDumpMemory(plist, (xmlChar **) & XML_content, &length); - - printf("XML Pairing request : %s\n", XML_content); + 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); + plist_add_sub_key_el(dict_record, "HostCertificate"); + plist_add_sub_data_el(dict_record, (const char*)host_cert.data, host_cert.size); + 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, "Request"); + plist_add_sub_string_el(dict, "Pair"); /* send to iPhone */ - ret = iphone_lckd_send(control, XML_content, length, &bytes); - - xmlFree(XML_content); - xmlFreeDoc(plist); - plist = NULL; + ret = iphone_lckd_send(control, dict); + plist_free(dict); + dict = NULL; if (ret != IPHONE_E_SUCCESS) return ret; /* Now get iPhone's answer */ - ret = iphone_lckd_recv(control, &XML_content, &bytes); + ret = iphone_lckd_recv(control, &dict); if (ret != IPHONE_E_SUCCESS) return ret; - log_debug_msg("lockdown_pair_device: iPhone's response to our pair request:\n"); - log_debug_msg(XML_content); - log_debug_msg("\n\n"); + 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); - 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; - } - if (!dict) { - free(public_key_b64); - return IPHONE_E_DICT_ERROR; - } + plist_type result_key_type = plist_get_node_type(result_key_node); + plist_type result_value_type = plist_get_node_type(result_value_node); - /* Parse xml to check success and to find public key */ - dictionary = read_dict_element_strings(dict); - xmlFreeDoc(plist); - free(XML_content); + if (result_key_type == PLIST_KEY && result_value_type == PLIST_STRING) { - 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; + + plist_get_key_val(result_key_node, &result_key); + plist_get_string_val(result_value_node, &result_value); + + if (!strcmp(result_key, "Result") && !strcmp(result_value, "Success")) { + ret = IPHONE_E_SUCCESS; } - } - if (dictionary) { - free_dictionary(dictionary); - dictionary = NULL; + free(result_key); + free(result_value); } + plist_free(dict); + dict = NULL; /* store public key in config if pairing succeeded */ - if (success) { - log_debug_msg("lockdownd_pair_device: pair success\n"); - store_device_public_key(uid, public_key_b64); + if (ret == IPHONE_E_SUCCESS) { + log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_pair_device: pair success\n"); + store_device_public_key(uid, public_key); ret = IPHONE_E_SUCCESS; } else { - log_debug_msg("lockdownd_pair_device: pair failure\n"); + log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_pair_device: pair failure\n"); ret = IPHONE_E_PAIRING_FAILED; } - free(public_key_b64); + free(public_key.data); return ret; } @@ -626,81 +635,71 @@ iphone_error_t lockdownd_pair_device(iphone_lckd_client_t control, char *uid, ch void 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; + iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; - 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; + plist_t dict = plist_new_dict(); + plist_add_sub_key_el(dict, "Request"); + plist_add_sub_string_el(dict, "Goodbye"); - xmlDocDumpMemory(plist, (xmlChar **) & XML_content, &length); - ret = iphone_lckd_send(control, XML_content, length, &bytes); + log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_close() called\n"); - xmlFree(XML_content); - xmlFreeDoc(plist); - plist = NULL; - ret = iphone_lckd_recv(control, &XML_content, &bytes); + ret = iphone_lckd_send(control, dict); + plist_free(dict); + dict = NULL; + + ret = iphone_lckd_recv(control, &dict); - plist = xmlReadMemory(XML_content, bytes, NULL, NULL, 0); - if (!plist) { - log_debug_msg("lockdownd_close(): IPHONE_E_PLIST_ERROR\n"); - return; //IPHONE_E_PLIST_ERROR; - } - dict = xmlDocGetRootElement(plist); - for (dict = dict->children; dict; dict = dict->next) { - if (!xmlStrcmp(dict->name, "dict")) - break; - } if (!dict) { - log_debug_msg("lockdownd_close(): IPHONE_E_DICT_ERROR\n"); - return; //IPHONE_E_DICT_ERROR; + log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_close(): IPHONE_E_PLIST_ERROR\n"); + return; // IPHONE_E_PLIST_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_close(): success\n"); + 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); + + plist_type result_type = plist_get_node_type(result_node); + plist_type value_type = plist_get_node_type(value_node); + + if (result_type == PLIST_KEY && value_type == PLIST_STRING) { + char *result_value = NULL; + char *value_value = NULL; + + plist_get_key_val(result_node, &result_value); + plist_get_string_val(value_node, &value_value); + + if (!strcmp(result_value, "Result") && !strcmp(value_value, "Success")) { + log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_close(): success\n"); ret = IPHONE_E_SUCCESS; - break; } + free(result_value); + free(value_value); } - - free_dictionary(dictionary); - return; //ret; + plist_free(dict); + dict = NULL; + return; // ret; } /** Generates the device certificate from the public key as well as the host * and root certificates. - * + * * @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; @@ -736,7 +735,7 @@ iphone_error_t lockdownd_gen_pair_cert(char *public_key_b64, char **device_cert_ gnutls_global_init(); gnutls_datum_t essentially_null = { strdup("abababababababab"), strlen("abababababababab") }; - gnutls_x509_privkey_t fake_privkey, root_privkey; + gnutls_x509_privkey_t fake_privkey, root_privkey, host_privkey; gnutls_x509_crt_t dev_cert, root_cert, host_cert; gnutls_x509_privkey_init(&fake_privkey); @@ -749,49 +748,50 @@ iphone_error_t lockdownd_gen_pair_cert(char *public_key_b64, char **device_cert_ &essentially_null, &essentially_null)) { gnutls_x509_privkey_init(&root_privkey); + gnutls_x509_privkey_init(&host_privkey); - /* get root cert */ - gnutls_datum_t pem_root_cert = { NULL, 0 }; - get_root_certificate(&pem_root_cert); - if (GNUTLS_E_SUCCESS != gnutls_x509_crt_import(root_cert, &pem_root_cert, GNUTLS_X509_FMT_PEM)) - ret = IPHONE_E_SSL_ERROR; - - /* get host cert */ - gnutls_datum_t pem_host_cert = { NULL, 0 }; - get_host_certificate(&pem_host_cert); - if (GNUTLS_E_SUCCESS != gnutls_x509_crt_import(host_cert, &pem_host_cert, GNUTLS_X509_FMT_PEM)) - ret = IPHONE_E_SSL_ERROR; - - /* get root private key */ - gnutls_datum_t pem_root_priv = { NULL, 0 }; - get_root_private_key(&pem_root_priv); - if (GNUTLS_E_SUCCESS != gnutls_x509_privkey_import(root_privkey, &pem_root_priv, GNUTLS_X509_FMT_PEM)) - ret = IPHONE_E_SSL_ERROR; - - /* 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); - gnutls_x509_crt_set_ca_status(dev_cert, 0); - gnutls_x509_crt_set_activation_time(dev_cert, time(NULL)); - gnutls_x509_crt_set_expiration_time(dev_cert, time(NULL) + (60 * 60 * 24 * 365 * 10)); - gnutls_x509_crt_sign(dev_cert, root_cert, root_privkey); + ret = get_keys_and_certs( root_privkey, root_cert, host_privkey, host_cert); if (IPHONE_E_SUCCESS == ret) { - /* if everything went well, export in PEM format */ - gnutls_datum_t dev_pem = { NULL, 0 }; - gnutls_x509_crt_export(dev_cert, GNUTLS_X509_FMT_PEM, NULL, &dev_pem.size); - 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); + + /* 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); + gnutls_x509_crt_set_ca_status(dev_cert, 0); + gnutls_x509_crt_set_activation_time(dev_cert, time(NULL)); + gnutls_x509_crt_set_expiration_time(dev_cert, time(NULL) + (60 * 60 * 24 * 365 * 10)); + gnutls_x509_crt_sign(dev_cert, root_cert, root_privkey); + + if (IPHONE_E_SUCCESS == ret) { + /* if everything went well, export in PEM format */ + gnutls_datum_t dev_pem = { NULL, 0 }; + gnutls_x509_crt_export(dev_cert, GNUTLS_X509_FMT_PEM, NULL, &dev_pem.size); + dev_pem.data = gnutls_malloc(dev_pem.size); + gnutls_x509_crt_export(dev_cert, GNUTLS_X509_FMT_PEM, dev_pem.data, &dev_pem.size); + + gnutls_datum_t pem_root_cert = { NULL, 0 }; + gnutls_datum_t pem_host_cert = { NULL, 0 }; + + if ( IPHONE_E_SUCCESS == get_certs_as_pem(&pem_root_cert, &pem_host_cert) ) { + /* 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; + + g_free(pem_root_cert.data); + g_free(pem_host_cert.data); + } + } } - gnutls_free(pem_root_priv.data); - gnutls_free(pem_root_cert.data); - gnutls_free(pem_host_cert.data); } } @@ -799,7 +799,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,129 +812,127 @@ 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; + uint32_t 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; - } - - xmlDocDumpMemory(plist, (xmlChar **) & what2send, &len); - ret = iphone_lckd_send(control, what2send, len, &bytes); + /* 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"); - xmlFree(what2send); - xmlFreeDoc(plist); + ret = iphone_lckd_send(control, dict); + 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); - if (!dict) - return IPHONE_E_DICT_ERROR; - for (dict = dict->children; dict; dict = dict->next) { - if (!xmlStrcmp(dict->name, "dict")) - break; - } - dictionary = read_dict_element_strings(dict); - xmlFreeDoc(plist); - free(what2send); + ret = iphone_lckd_recv(control, &dict); + + if (!dict) + 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); + + plist_type result_key_type = plist_get_node_type(result_key_node); + plist_type result_value_type = plist_get_node_type(result_value_node); + + if (result_key_type == PLIST_KEY && result_value_type == PLIST_STRING) { + char *result_key = NULL; + char *result_value = NULL; + + plist_get_key_val(result_key_node, &result_key); + plist_get_string_val(result_value_node, &result_value); + 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); + if (!strcmp(result_key, "Result") && !strcmp(result_value, "Success")) { + // Set up GnuTLS... + //gnutls_anon_client_credentials_t anoncred; + gnutls_certificate_credentials_t xcred; + + log_dbg_msg(DBGMASK_LOCKDOWND, "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")) { - // we need to store the session ID for StopSession - strcpy(control->session_id, dictionary[i + 1]); - log_debug_msg("SessionID: %s\n", control->session_id); - free_dictionary(dictionary); - return ret; + } + gnutls_credentials_set(*control->ssl_session, GNUTLS_CRD_CERTIFICATE, xcred); // this part is killing me. + + log_dbg_msg(DBGMASK_LOCKDOWND, "GnuTLS step 1...\n"); + gnutls_transport_set_ptr(*control->ssl_session, (gnutls_transport_ptr_t) control); + log_dbg_msg(DBGMASK_LOCKDOWND, "GnuTLS step 2...\n"); + gnutls_transport_set_push_function(*control->ssl_session, (gnutls_push_func) & lockdownd_secuwrite); + log_dbg_msg(DBGMASK_LOCKDOWND, "GnuTLS step 3...\n"); + gnutls_transport_set_pull_function(*control->ssl_session, (gnutls_pull_func) & lockdownd_securead); + log_dbg_msg(DBGMASK_LOCKDOWND, "GnuTLS step 4 -- now handshaking...\n"); + + if (errno) + log_dbg_msg(DBGMASK_LOCKDOWND, "WARN: errno says %s before handshake!\n", strerror(errno)); + return_me = gnutls_handshake(*control->ssl_session); + log_dbg_msg(DBGMASK_LOCKDOWND, "GnuTLS handshake done...\n"); + + if (return_me != GNUTLS_E_SUCCESS) { + log_dbg_msg(DBGMASK_LOCKDOWND, "GnuTLS reported something wrong.\n"); + gnutls_perror(return_me); + log_dbg_msg(DBGMASK_LOCKDOWND, "oh.. errno says %s\n", strerror(errno)); + return IPHONE_E_SSL_ERROR; + } else { + control->in_SSL = 1; + ret = IPHONE_E_SUCCESS; } } - if (ret == IPHONE_E_SUCCESS) { - log_debug_msg("Failed to get SessionID!\n"); - return ret; - } + } + //store session id + plist_t session_node = plist_find_node_by_key(dict, "SessionID"); + if (session_node) { + + plist_t session_node_val = plist_get_next_sibling(session_node); + plist_type session_node_val_type = plist_get_node_type(session_node_val); + + if (session_node_val_type == PLIST_STRING) { - 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]); + char *session_id = NULL; + plist_get_string_val(session_node_val, &session_id); + + if (session_node_val_type == PLIST_STRING && session_id) { + // we need to store the session ID for StopSession + strcpy(control->session_id, session_id); + log_dbg_msg(DBGMASK_LOCKDOWND, "SessionID: %s\n", control->session_id); + } + free(session_id); } + } else + log_dbg_msg(DBGMASK_LOCKDOWND, "Failed to get SessionID!\n"); + plist_free(dict); + dict = NULL; + if (ret == IPHONE_E_SUCCESS) + return ret; - free_dictionary(dictionary); - return IPHONE_E_SSL_ERROR; - } else { - log_debug_msg("Didn't get enough bytes.\n"); - return IPHONE_E_NOT_ENOUGH_DATA; - } + log_dbg_msg(DBGMASK_LOCKDOWND, "Apparently failed negotiating with lockdownd.\n"); + return IPHONE_E_SSL_ERROR; } /** gnutls callback for writing data to the iPhone. @@ -951,10 +948,10 @@ ssize_t lockdownd_secuwrite(gnutls_transport_ptr_t transport, char *buffer, size int bytes = 0; iphone_lckd_client_t control; control = (iphone_lckd_client_t) transport; - log_debug_msg("lockdownd_secuwrite() called\n"); - log_debug_msg("pre-send\nlength = %zi\n", length); + log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_secuwrite() called\n"); + log_dbg_msg(DBGMASK_LOCKDOWND, "pre-send\nlength = %zi\n", length); iphone_mux_send(control->connection, buffer, length, &bytes); - log_debug_msg("post-send\nsent %i bytes\n", bytes); + log_dbg_msg(DBGMASK_LOCKDOWND, "post-send\nsent %i bytes\n", bytes); dump_debug_buffer("sslpacketwrite.out", buffer, length); return bytes; @@ -1038,86 +1035,72 @@ 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; + uint32_t port_loc = 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); - xmlDocDumpMemory(plist, (xmlChar **) & XML_query, &length); + /* send to iPhone */ + ret = iphone_lckd_send(client, dict); + 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, &dict); + if (IPHONE_E_SUCCESS != ret) return ret; - 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; - } + if (!dict) + return IPHONE_E_PLIST_ERROR; - if (!dict) - return IPHONE_E_UNKNOWN_ERROR; - dictionary = read_dict_element_strings(dict); + 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); - for (i = 0; dictionary[i]; i += 2) { - log_debug_msg("lockdownd_start_service() dictionary %s: %s\n", dictionary[i], dictionary[i + 1]); + plist_t port_key_node = plist_find_node_by_key(dict, "Port"); + plist_t port_value_node = plist_get_next_sibling(port_key_node); - if (!xmlStrcmp(dictionary[i], "Port")) { - port_loc = atoi(dictionary[i + 1]); - log_debug_msg("lockdownd_start_service() atoi'd port: %i\n", port); - } + plist_type result_key_type = plist_get_node_type(result_key_node); + plist_type result_value_type = plist_get_node_type(result_value_node); + plist_type port_key_type = plist_get_node_type(port_key_node); + plist_type port_value_type = plist_get_node_type(port_value_node); - if (!xmlStrcmp(dictionary[i], "Result")) { - if (!xmlStrcmp(dictionary[i + 1], "Success")) { - result = 1; - } - } - } + if (result_key_type == PLIST_KEY && result_value_type == PLIST_STRING && port_key_type == PLIST_KEY + && port_value_type == PLIST_UINT) { - log_debug_msg("lockdownd_start_service(): DATA RECEIVED:\n\n"); - log_debug_msg(XML_query); - log_debug_msg("end data received by lockdownd_start_service()\n"); + char *result_key = NULL; + char *result_value = NULL; + char *port_key = NULL; + uint64_t port_value = 0; - free(XML_query); - xmlFreeDoc(plist); - free_dictionary(dictionary); - if (port && result) { + plist_get_key_val(result_key_node, &result_key); + plist_get_string_val(result_value_node, &result_value); + plist_get_key_val(port_key_node, &port_key); + plist_get_uint_val(port_value_node, &port_value); + + if (!strcmp(result_key, "Result") && !strcmp(result_value, "Success") && !strcmp(port_key, "Port")) { + port_loc = port_value; + ret = IPHONE_E_SUCCESS; + } + + if (port && ret == IPHONE_E_SUCCESS) *port = port_loc; - return IPHONE_E_SUCCESS; - } else - return IPHONE_E_UNKNOWN_ERROR; + else + ret = IPHONE_E_UNKNOWN_ERROR; } - return IPHONE_E_UNKNOWN_ERROR; + plist_free(dict); + dict = NULL; + return ret; } diff --git a/src/lockdown.h b/src/lockdown.h index c30a182..7485006 100644 --- a/src/lockdown.h +++ b/src/lockdown.h @@ -8,22 +8,21 @@ * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef LOCKDOWND_H #define LOCKDOWND_H #include "usbmux.h" -#include "plist.h" #include <gnutls/gnutls.h> #include <string.h> @@ -39,17 +38,17 @@ struct iphone_lckd_client_int { char session_id[40]; }; -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); + 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(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); +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); void lockdownd_close(iphone_lckd_client_t control); // SSL functions diff --git a/src/plist.c b/src/plist.c deleted file mode 100644 index b9d9e6a..0000000 --- a/src/plist.c +++ /dev/null @@ -1,245 +0,0 @@ -/* - * plist.c - * Builds plist XML structures. - * - * Copyright (c) 2008 Zach C. All Rights Reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <libxml/parser.h> -#include <libxml/tree.h> -#include <string.h> -#include <assert.h> -#include "plist.h" - -const char *plist_base = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\ -<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n\ -<plist version=\"1.0\">\n\ -</plist>\0"; - -/** Formats a block of text to be a given indentation and width. - * - * The total width of the return string will be depth + cols. - * - * @param buf The string to format. - * @param cols The number of text columns for returned block of text. - * @param depth The number of tabs to indent the returned block of text. - * - * @return The formatted string. - */ -static char *format_string(const char *buf, int cols, int depth) -{ - int colw = depth + cols + 1; - int len = strlen(buf); - int nlines = len / cols + 1; - char *new_buf = (char *) malloc(nlines * colw + depth + 1); - int i = 0; - int j = 0; - - assert(cols >= 0); - assert(depth >= 0); - - // Inserts new lines and tabs at appropriate locations - for (i = 0; i < nlines; i++) { - new_buf[i * colw] = '\n'; - for (j = 0; j < depth; j++) - new_buf[i * colw + 1 + j] = '\t'; - memcpy(new_buf + i * colw + 1 + depth, buf + i * cols, cols); - } - new_buf[len + (1 + depth) * nlines] = '\n'; - - // Inserts final row of indentation and termination character - for (j = 0; j < depth; j++) - new_buf[len + (1 + depth) * nlines + 1 + j] = '\t'; - new_buf[len + (1 + depth) * nlines + depth + 1] = '\0'; - - return new_buf; -} - -/** Creates a new plist XML document. - * - * @return The plist XML document. - */ -xmlDocPtr new_plist(void) -{ - char *plist = strdup(plist_base); - xmlDocPtr plist_xml = xmlReadMemory(plist, strlen(plist), NULL, NULL, 0); - - if (!plist_xml) - return NULL; - - free(plist); - - return plist_xml; -} - -/** Destroys a previously created XML document. - * - * @param plist The XML document to destroy. - */ -void free_plist(xmlDocPtr plist) -{ - if (!plist) - return; - - xmlFreeDoc(plist); -} - -/** Adds a new node as a child to a given node. - * - * This is a lower level function so you probably want to use - * add_key_str_dict_element, add_key_dict_node or add_key_data_dict_element - * instead. - * - * @param plist The plist XML document to which the to_node belongs. - * @param name The name of the new node. - * @param content The string containing the text node of the new node. - * @param to_node The node to attach the child node to. If none is given, the - * root node of the given document is used. - * @param depth The number of tabs to indent the new node. - * - * @return The newly created node. - */ -xmlNode *add_child_to_plist(xmlDocPtr plist, const char *name, const char *content, xmlNode * to_node, int depth) -{ - int i = 0; - xmlNode *child; - - if (!plist) - return NULL; - assert(depth >= 0); - if (!to_node) - to_node = xmlDocGetRootElement(plist); - - for (i = 0; i < depth; i++) { - xmlNodeAddContent(to_node, "\t"); - } - child = xmlNewChild(to_node, NULL, name, content); - xmlNodeAddContent(to_node, "\n"); - - return child; -} - -/** Adds a string key-pair to a plist XML document. - * - * @param plist The plist XML document to add the new node to. - * @param dict The dictionary node within the plist XML document to add the new node to. - * @param key The string containing the key value. - * @param value The string containing the value. - * @param depth The number of tabs to indent the new node. - * - * @return The newly created key node. - */ -xmlNode *add_key_str_dict_element(xmlDocPtr plist, xmlNode * dict, const char *key, const char *value, int depth) -{ - xmlNode *keyPtr; - - keyPtr = add_child_to_plist(plist, "key", key, dict, depth); - add_child_to_plist(plist, "string", value, dict, depth); - - return keyPtr; -} - -/** Adds a new dictionary key-pair to a plist XML document. - * - * @param plist The plist XML document to add the new node to. - * @param dict The dictionary node within the plist XML document to add the new node to. - * @param key The string containing the key value. - * @param value The string containing the value. - * @param depth The number of tabs to indent the new node. - * - * @return The newly created dict node. - */ -xmlNode *add_key_dict_node(xmlDocPtr plist, xmlNode * dict, const char *key, const char *value, int depth) -{ - xmlNode *child; - - add_child_to_plist(plist, "key", key, dict, depth); - child = add_child_to_plist(plist, "dict", value, dict, depth); - - return child; -} - -/** Adds a new data dictionary key-pair to a plist XML document. - * - * @param plist The plist XML document to add the new node to. - * @param dict The dictionary node within the plist XML document to add the new node to. - * @param key The string containing the key value. - * @param value The string containing the value. - * @param depth The number of tabs to indent the new node. - * - * @return The newly created key node. - */ -xmlNode *add_key_data_dict_element(xmlDocPtr plist, xmlNode * dict, const char *key, const char *value, int depth) -{ - xmlNode *keyPtr; - - keyPtr = add_child_to_plist(plist, "key", key, dict, depth); - add_child_to_plist(plist, "data", format_string(value, 60, depth), dict, depth); - - return keyPtr; -} - -/** Reads a set of keys and strings into an array from a plist XML document. - * - * @param dict The root XMLNode of a plist XML document to be read. - * - * @return An array where each even number is a key and the odd numbers are - * values. If the odd number is \0, that's the end of the list. - */ -char **read_dict_element_strings(xmlNode * dict) -{ - char **return_me = NULL, **old = NULL; - int current_length = 0; - int current_pos = 0; - xmlNode *dict_walker; - - for (dict_walker = dict->children; dict_walker; dict_walker = dict_walker->next) { - if (!xmlStrcmp(dict_walker->name, "key")) { - current_length += 2; - old = return_me; - return_me = realloc(return_me, sizeof(char *) * current_length); - if (!return_me) { - free(old); - return NULL; - } - return_me[current_pos++] = xmlNodeGetContent(dict_walker); - return_me[current_pos++] = xmlNodeGetContent(dict_walker->next->next); - } - } - - old = return_me; - return_me = realloc(return_me, sizeof(char *) * (current_length + 1)); - return_me[current_pos] = NULL; - - return return_me; -} - -/** Destroys a dictionary as returned by read_dict_element_strings - */ -void free_dictionary(char **dictionary) -{ - int i = 0; - - if (!dictionary) - return; - - for (i = 0; dictionary[i]; i++) { - free(dictionary[i]); - } - - free(dictionary); -} diff --git a/src/plist.h b/src/plist.h deleted file mode 100644 index cd2028e..0000000 --- a/src/plist.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * plist.h - * contains structures and the like for plists - * - * Copyright (c) 2008 Zach C. All Rights Reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef PLIST_H -#define PLIST_H - -#include <libxml/parser.h> -#include <libxml/tree.h> - -xmlNode *add_key_dict_node(xmlDocPtr plist, xmlNode * dict, const char *key, const char *value, int depth); -xmlNode *add_key_str_dict_element(xmlDocPtr plist, xmlNode * dict, const char *key, const char *value, int depth); -xmlNode *add_key_data_dict_element(xmlDocPtr plist, xmlNode * dict, const char *key, const char *value, int depth); -xmlNode *add_child_to_plist(xmlDocPtr plist, const char *name, const char *content, xmlNode * to_node, int depth); - -void free_plist(xmlDocPtr plist); -xmlDocPtr new_plist(void); - -char **read_dict_element_strings(xmlNode * dict); -void free_dictionary(char **dictionary); -#endif diff --git a/src/usbmux.c b/src/usbmux.c index d8e6b44..22ce588 100644 --- a/src/usbmux.c +++ b/src/usbmux.c @@ -38,7 +38,7 @@ static int clients = 0; * * @return A USBMux packet */ -usbmux_tcp_header *new_mux_packet(uint16 s_port, uint16 d_port) +usbmux_tcp_header *new_mux_packet(uint16_t s_port, uint16_t d_port) { usbmux_tcp_header *conn = (usbmux_tcp_header *) malloc(sizeof(usbmux_tcp_header)); conn->type = htonl(6); @@ -314,6 +314,7 @@ iphone_error_t iphone_mux_recv(iphone_umux_client_t client, char *data, uint32_t } else { memcpy(data, client->recv_buffer, client->r_len); free(client->recv_buffer); // don't need to deal with anymore, but... + client->recv_buffer = NULL; offset = client->r_len; // see #2b, above client->r_len = 0; } diff --git a/src/usbmux.h b/src/usbmux.h index fd5fc78..bea83f7 100644 --- a/src/usbmux.h +++ b/src/usbmux.h @@ -22,6 +22,7 @@ #include <sys/types.h> #include <stdlib.h> #include <stdint.h> +#include "libiphone/libiphone.h" #ifndef USBMUX_H #define USBMUX_H @@ -30,17 +31,12 @@ #include "iphone.h" #endif -typedef uint16_t uint16; -typedef uint32_t uint32; -typedef uint8_t uint8; - - typedef struct { - uint32 type, length; - uint16 sport, dport; - uint32 scnt, ocnt; - uint8 offset, tcp_flags; - uint16 window, nullnull, length16; + uint32_t type, length; + uint16_t sport, dport; + uint32_t scnt, ocnt; + uint8_t offset, tcp_flags; + uint16_t window, nullnull, length16; } usbmux_tcp_header; struct iphone_umux_client_int { @@ -50,10 +46,10 @@ struct iphone_umux_client_int { int r_len; }; -usbmux_tcp_header *new_mux_packet(uint16 s_port, uint16 d_port); +usbmux_tcp_header *new_mux_packet(uint16_t s_port, uint16_t d_port); typedef struct { - uint32 type, length, major, minor, allnull; + uint32_t type, length, major, minor, allnull; } usbmux_version_header; usbmux_version_header *version_header(void); diff --git a/src/userpref.c b/src/userpref.c index 5f227b0..0e83133 100644 --- a/src/userpref.c +++ b/src/userpref.c @@ -8,25 +8,28 @@ * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include <glib.h> #include <glib/gprintf.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> +#include <gnutls/gnutls.h> +#include <gnutls/x509.h> +#include <gcrypt.h> + #include "userpref.h" #include "utils.h" -#include <string.h> -#include <stdlib.h> #define LIBIPHONE_CONF_DIR "libiphone" #define LIBIPHONE_CONF_FILE "libiphonerc" @@ -49,9 +52,75 @@ static void create_config_dir(void) g_free(config_dir); } +static int get_rand(int min, int max) +{ + int retval = (rand() % (max - min)) + min; + return retval; +} + +/** Generates a valid HostID (which is actually a UUID). + * + * @return A null terminated string containing a valid HostID. + */ +static char *lockdownd_generate_hostid() +{ + char *hostid = (char *) malloc(sizeof(char) * 37); // HostID's are just UUID's, and UUID's are 36 characters long + const char *chars = "ABCDEF0123456789"; + srand(time(NULL)); + int i = 0; + + for (i = 0; i < 36; i++) { + if (i == 8 || i == 13 || i == 18 || i == 23) { + hostid[i] = '-'; + continue; + } else { + hostid[i] = chars[get_rand(0, 16)]; + } + } + hostid[36] = '\0'; // make it a real string + return hostid; +} + +/** Store HostID in config file. + * + * @param host_id A null terminated string containing a valid HostID. + */ +static int write_host_id(char *host_id) +{ + GKeyFile *key_file; + gsize length; + gchar *buf, *config_file; + GIOChannel *file; + + if (!host_id) + return 0; + + /* Make sure config directory exists */ + create_config_dir(); + + /* Now parse file to get the HostID */ + key_file = g_key_file_new(); -/** Reads the HostID from a previously generated configuration file. - * + /* Store in config file */ + log_debug_msg("init_config_file(): setting hostID to %s\n", host_id); + g_key_file_set_value(key_file, "Global", "HostID", host_id); + + /* Write config file on disk */ + buf = g_key_file_to_data(key_file, &length, NULL); + config_file = + g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIPHONE_CONF_DIR, LIBIPHONE_CONF_FILE, NULL); + file = g_io_channel_new_file(config_file, "w", NULL); + g_free(config_file); + g_io_channel_write_chars(file, buf, length, NULL, NULL); + g_io_channel_shutdown(file, TRUE, NULL); + g_io_channel_unref(file); + + g_key_file_free(key_file); + return 1; +} + +/** Reads the HostID from a previously generated configuration file. + * * @note It is the responsibility of the calling function to free the returned host_id * * @return The string containing the HostID or NULL @@ -77,6 +146,12 @@ char *get_host_id(void) g_key_file_free(key_file); g_free(config_file); + if (!host_id) { + //no config, generate host_id + host_id = lockdownd_generate_hostid(); + write_host_id(host_id); + } + log_debug_msg("get_host_id(): Using %s as HostID\n", host_id); return host_id; } @@ -111,10 +186,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 +199,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; } @@ -160,56 +231,220 @@ static int read_file_in_confdir(const char *file, gnutls_datum_t * data) g_free(filepath); /* Add it to the gnutls_datnum_t structure */ - data->data = content; + data->data = (uint8_t*) content; data->size = size; return success; } -/** Read the root private key - * - * @param root_privkey A pointer to the appropriate gnutls structure + +/** Private function which generate private keys and certificates. * - * @return 1 if the file was successfully read and 0 otherwise. + * @return IPHONE_E_SUCCESS if keys were successfully generated. */ -int get_root_private_key(gnutls_datum_t * root_privkey) +static iphone_error_t gen_keys_and_cert(void) { - return read_file_in_confdir(LIBIPHONE_ROOT_PRIVKEY, root_privkey); + iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; + gnutls_x509_privkey_t root_privkey; + gnutls_x509_privkey_t host_privkey; + gnutls_x509_crt_t root_cert; + gnutls_x509_crt_t host_cert; + + gnutls_global_deinit(); + gnutls_global_init(); + + //use less secure random to speed up key generation + gcry_control(GCRYCTL_ENABLE_QUICK_RANDOM); + + gnutls_x509_privkey_init(&root_privkey); + gnutls_x509_privkey_init(&host_privkey); + + gnutls_x509_crt_init(&root_cert); + gnutls_x509_crt_init(&host_cert); + + /* generate root key */ + gnutls_x509_privkey_generate(root_privkey, GNUTLS_PK_RSA, 2048, 0); + gnutls_x509_privkey_generate(host_privkey, GNUTLS_PK_RSA, 2048, 0); + + /* generate certificates */ + gnutls_x509_crt_set_key(root_cert, root_privkey); + gnutls_x509_crt_set_serial(root_cert, "\x00", 1); + gnutls_x509_crt_set_version(root_cert, 3); + gnutls_x509_crt_set_ca_status(root_cert, 1); + gnutls_x509_crt_set_activation_time(root_cert, time(NULL)); + gnutls_x509_crt_set_expiration_time(root_cert, time(NULL) + (60 * 60 * 24 * 365 * 10)); + gnutls_x509_crt_sign(root_cert, root_cert, root_privkey); + + + gnutls_x509_crt_set_key(host_cert, host_privkey); + gnutls_x509_crt_set_serial(host_cert, "\x00", 1); + gnutls_x509_crt_set_version(host_cert, 3); + gnutls_x509_crt_set_ca_status(host_cert, 0); + gnutls_x509_crt_set_key_usage(host_cert, GNUTLS_KEY_KEY_ENCIPHERMENT | GNUTLS_KEY_DIGITAL_SIGNATURE); + gnutls_x509_crt_set_activation_time(host_cert, time(NULL)); + gnutls_x509_crt_set_expiration_time(host_cert, time(NULL) + (60 * 60 * 24 * 365 * 10)); + gnutls_x509_crt_sign(host_cert, root_cert, root_privkey); + + /* export to PEM format */ + gnutls_datum_t root_key_pem = { NULL, 0 }; + gnutls_datum_t host_key_pem = { NULL, 0 }; + + gnutls_x509_privkey_export(root_privkey, GNUTLS_X509_FMT_PEM, NULL, &root_key_pem.size); + gnutls_x509_privkey_export(host_privkey, GNUTLS_X509_FMT_PEM, NULL, &host_key_pem.size); + + root_key_pem.data = gnutls_malloc(root_key_pem.size); + host_key_pem.data = gnutls_malloc(host_key_pem.size); + + gnutls_x509_privkey_export(root_privkey, GNUTLS_X509_FMT_PEM, root_key_pem.data, &root_key_pem.size); + gnutls_x509_privkey_export(host_privkey, GNUTLS_X509_FMT_PEM, host_key_pem.data, &host_key_pem.size); + + gnutls_datum_t root_cert_pem = { NULL, 0 }; + gnutls_datum_t host_cert_pem = { NULL, 0 }; + + gnutls_x509_crt_export(root_cert, GNUTLS_X509_FMT_PEM, NULL, &root_cert_pem.size); + gnutls_x509_crt_export(host_cert, GNUTLS_X509_FMT_PEM, NULL, &host_cert_pem.size); + + root_cert_pem.data = gnutls_malloc(root_cert_pem.size); + host_cert_pem.data = gnutls_malloc(host_cert_pem.size); + + gnutls_x509_crt_export(root_cert, GNUTLS_X509_FMT_PEM, root_cert_pem.data, &root_cert_pem.size); + gnutls_x509_crt_export(host_cert, GNUTLS_X509_FMT_PEM, host_cert_pem.data, &host_cert_pem.size); + + if (NULL != root_cert_pem.data && 0 != root_cert_pem.size && + NULL != host_cert_pem.data && 0 != host_cert_pem.size) + ret = IPHONE_E_SUCCESS; + + /* store values in config file */ + init_config_file( &root_key_pem, &host_key_pem, &root_cert_pem, &host_cert_pem); + + gnutls_free(root_key_pem.data); + gnutls_free(host_key_pem.data); + gnutls_free(root_cert_pem.data); + gnutls_free(host_cert_pem.data); + + //restore gnutls env + gnutls_global_deinit(); + gnutls_global_init(); + + return ret; } -/** Read the host private key +/** Private function which import the given key into a gnutls structure. * - * @param host_privkey A pointer to the appropriate gnutls structure + * @param key_name The filename of the private key to import. + * @param key the gnutls key structure. * - * @return 1 if the file was successfully read and 0 otherwise. + * @return IPHONE_E_SUCCESS if the key was successfully imported. */ -int get_host_private_key(gnutls_datum_t * host_privkey) +static iphone_error_t import_key(const char* key_name, gnutls_x509_privkey_t key) { - return read_file_in_confdir(LIBIPHONE_HOST_PRIVKEY, host_privkey); + iphone_error_t ret = IPHONE_E_INVALID_CONF; + gnutls_datum_t pem_key = { NULL, 0 }; + + if ( read_file_in_confdir(key_name, &pem_key) ) { + if (GNUTLS_E_SUCCESS == gnutls_x509_privkey_import(key, &pem_key, GNUTLS_X509_FMT_PEM)) + ret = IPHONE_E_SUCCESS; + else + ret = IPHONE_E_SSL_ERROR; + } + gnutls_free(pem_key.data); + return ret; } -/** Read the root certificate +/** Private function which import the given certificate into a gnutls structure. * - * @param root_privkey A pointer to the appropriate gnutls structure + * @param crt_name The filename of the certificate to import. + * @param cert the gnutls certificate structure. * - * @return 1 if the file was successfully read and 0 otherwise. + * @return IPHONE_E_SUCCESS if the certificate was successfully imported. */ -int get_root_certificate(gnutls_datum_t * root_cert) +static iphone_error_t import_crt(const char* crt_name, gnutls_x509_crt_t cert) { - return read_file_in_confdir(LIBIPHONE_ROOT_CERTIF, root_cert); + iphone_error_t ret = IPHONE_E_INVALID_CONF; + gnutls_datum_t pem_cert = { NULL, 0 }; + + if ( read_file_in_confdir(crt_name, &pem_cert) ) { + if (GNUTLS_E_SUCCESS == gnutls_x509_crt_import(cert, &pem_cert, GNUTLS_X509_FMT_PEM)) + ret = IPHONE_E_SUCCESS; + else + ret = IPHONE_E_SSL_ERROR; + } + gnutls_free(pem_cert.data); + return ret; } -/** Read the host certificate +/** Function to retrieve host keys and certificates. + * This function trigger key generation if they do not exists yet or are invalid. * - * @param root_privkey A pointer to the appropriate gnutls structure + * @note This function can take few seconds to complete (typically 5 seconds) * - * @return 1 if the file was successfully read and 0 otherwise. + * @param root_privkey The root private key. + * @param root_crt The root certificate. + * @param host_privkey The host private key. + * @param host_crt The host certificate. + * + * @return IPHONE_E_SUCCESS if the keys and certificates were successfully retrieved. */ -int get_host_certificate(gnutls_datum_t * host_cert) +iphone_error_t get_keys_and_certs(gnutls_x509_privkey_t root_privkey, gnutls_x509_crt_t root_crt, gnutls_x509_privkey_t host_privkey, gnutls_x509_crt_t host_crt) { - return read_file_in_confdir(LIBIPHONE_HOST_CERTIF, host_cert); + iphone_error_t ret = IPHONE_E_SUCCESS; + + if (ret == IPHONE_E_SUCCESS) + ret = import_key(LIBIPHONE_ROOT_PRIVKEY, root_privkey); + + if (ret == IPHONE_E_SUCCESS) + ret = import_key(LIBIPHONE_HOST_PRIVKEY, host_privkey); + + if (ret == IPHONE_E_SUCCESS) + ret = import_crt(LIBIPHONE_ROOT_CERTIF, root_crt); + + if (ret == IPHONE_E_SUCCESS) + ret = import_crt(LIBIPHONE_HOST_CERTIF, host_crt); + + + if (IPHONE_E_SUCCESS != ret) { + //we had problem reading or importing root cert + //try with a new ones. + ret = gen_keys_and_cert(); + + if (ret == IPHONE_E_SUCCESS) + ret = import_key(LIBIPHONE_ROOT_PRIVKEY, root_privkey); + + if (ret == IPHONE_E_SUCCESS) + ret = import_key(LIBIPHONE_HOST_PRIVKEY, host_privkey); + + if (ret == IPHONE_E_SUCCESS) + ret = import_crt(LIBIPHONE_ROOT_CERTIF, root_crt); + + if (ret == IPHONE_E_SUCCESS) + ret = import_crt(LIBIPHONE_HOST_CERTIF, host_crt); + } + + return ret; } +/** Function to retrieve certificates encoded in PEM format. + * + * @param pem_root_cert The root certificate. + * @param pem_host_cert The host certificate. + * + * @return IPHONE_E_SUCCESS if the certificates were successfully retrieved. + */ +iphone_error_t get_certs_as_pem(gnutls_datum_t *pem_root_cert, gnutls_datum_t *pem_host_cert) +{ + iphone_error_t ret = IPHONE_E_INVALID_CONF; + + if ( !pem_root_cert || !pem_host_cert) + return IPHONE_E_INVALID_ARG; + + if ( read_file_in_confdir(LIBIPHONE_ROOT_CERTIF, pem_root_cert) && read_file_in_confdir(LIBIPHONE_HOST_CERTIF, pem_host_cert)) + ret = IPHONE_E_SUCCESS; + else { + g_free(pem_root_cert->data); + g_free(pem_host_cert->data); + } + return ret; +} /** Create and save a configuration file containing the given data. * * @note: All fields must specified and be non-null @@ -222,41 +457,18 @@ int get_host_certificate(gnutls_datum_t * host_cert) * * @return 1 on success and 0 otherwise. */ -int init_config_file(char *host_id, gnutls_datum_t * root_key, gnutls_datum_t * host_key, gnutls_datum_t * root_cert, +int init_config_file( gnutls_datum_t * root_key, gnutls_datum_t * host_key, gnutls_datum_t * root_cert, gnutls_datum_t * host_cert) { FILE *pFile; gchar *pem; - GKeyFile *key_file; - gsize length; - gchar *buf, *config_file; - GIOChannel *file; - if (!host_id || !root_key || !host_key || !root_cert || !host_cert) + if (!root_key || !host_key || !root_cert || !host_cert) return 0; /* Make sure config directory exists */ create_config_dir(); - /* Now parse file to get the HostID */ - key_file = g_key_file_new(); - - /* Store in config file */ - log_debug_msg("init_config_file(): setting hostID to %s\n", host_id); - g_key_file_set_value(key_file, "Global", "HostID", host_id); - - /* Write config file on disk */ - buf = g_key_file_to_data(key_file, &length, NULL); - config_file = - g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIPHONE_CONF_DIR, LIBIPHONE_CONF_FILE, NULL); - file = g_io_channel_new_file(config_file, "w", NULL); - g_free(config_file); - g_io_channel_write_chars(file, buf, length, NULL, NULL); - g_io_channel_shutdown(file, TRUE, NULL); - g_io_channel_unref(file); - - g_key_file_free(key_file); - /* Now write keys and certificates to disk */ pem = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIPHONE_CONF_DIR, LIBIPHONE_ROOT_PRIVKEY, NULL); pFile = fopen(pem, "wb"); diff --git a/src/userpref.h b/src/userpref.h index e7835d0..deced04 100644 --- a/src/userpref.h +++ b/src/userpref.h @@ -8,64 +8,34 @@ * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef USERPREF_H #define USERPREF_H #include <gnutls/gnutls.h> -/** - * Method to get user's HostID. Caller must free returned buffer. - * - * @return the HostID if exist in config file. Returns NULL otherwise. - */ -char *get_host_id(void); +#include "libiphone/libiphone.h" -/** - * Determine if we already paired this device. - * - * @return 1 if device is already paired. Returns 0 otherwise. - */ -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); +iphone_error_t get_keys_and_certs(gnutls_x509_privkey_t root_privkey, gnutls_x509_crt_t root_crt, gnutls_x509_privkey_t host_privkey, gnutls_x509_crt_t host_crt); -/** - * @return 1 if everything went well. Returns 0 otherwise. - */ -int get_root_private_key(gnutls_datum_t * root_privkey); +iphone_error_t get_certs_as_pem(gnutls_datum_t *pem_root_cert, gnutls_datum_t *pem_host_cert); -/** - * @return 1 if everything went well. Returns 0 otherwise. - */ -int get_host_private_key(gnutls_datum_t * host_privkey); +char *get_host_id(void); -/** - * @return 1 if everything went well. Returns 0 otherwise. - */ -int get_root_certificate(gnutls_datum_t * root_cert); +int is_device_known(char *uid); -/** - * @return 1 if everything went well. Returns 0 otherwise. - */ -int get_host_certificate(gnutls_datum_t * host_cert); +int store_device_public_key(char *uid, gnutls_datum_t public_key); -/** - * Setup a brand new config file. - * @return 1 if everything went well. Returns 0 otherwise. - */ -int init_config_file(char *host_id, gnutls_datum_t * root_key, gnutls_datum_t * host_key, gnutls_datum_t * root_cert, +int init_config_file( gnutls_datum_t * root_key, gnutls_datum_t * host_key, gnutls_datum_t * root_cert, gnutls_datum_t * host_cert); #endif diff --git a/src/utils.c b/src/utils.c index fb98471..5b0872d 100644 --- a/src/utils.c +++ b/src/utils.c @@ -23,6 +23,7 @@ #include "utils.h" int toto_debug = 0; +uint16_t dbg_mask = 0; /** * Sets the level of debugging. Currently the only acceptable values are 0 and @@ -36,6 +37,15 @@ void iphone_set_debug(int level) } +/** + * Set debug ids to display. Values can be OR-ed + * + * @param level Set to 0 for no debugging or 1 for debugging. + */ +void iphone_set_debug_mask(uint16_t mask) +{ + dbg_mask = mask; +} void log_debug_msg(const char *format, ...) { @@ -53,6 +63,21 @@ void log_debug_msg(const char *format, ...) #endif } +void log_dbg_msg(uint16_t id, const char *format, ...) +{ +#ifndef STRIP_DEBUG_CODE + if (id & dbg_mask) { + va_list args; + /* run the real fprintf */ + va_start(args, format); + + vfprintf(stderr, format, args); + + va_end(args); + } +#endif +} + inline void log_debug_buffer(const char *data, const int length) { #ifndef STRIP_DEBUG_CODE diff --git a/src/utils.h b/src/utils.h index 489f610..1750b8e 100644 --- a/src/utils.h +++ b/src/utils.h @@ -24,7 +24,11 @@ #include "libiphone/libiphone.h" + + inline void log_debug_msg(const char *format, ...); +inline void log_dbg_msg(uint16_t id, const char *format, ...); + inline void log_debug_buffer(const char *data, const int length); inline void dump_debug_buffer(const char *file, const char *data, const int length); #endif |