summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--configure.ac1
-rw-r--r--dev/Makefile.am3
-rw-r--r--dev/lckdclient.c1
-rw-r--r--dev/main.c2
-rw-r--r--src/AFC.c51
-rw-r--r--src/AFC.h10
-rw-r--r--src/Makefile.am8
-rw-r--r--src/initconf.c30
-rw-r--r--src/lockdown.c810
-rw-r--r--src/lockdown.h15
-rw-r--r--src/plist.c245
-rw-r--r--src/plist.h38
-rw-r--r--src/usbmux.c2
-rw-r--r--src/usbmux.h20
-rw-r--r--src/userpref.c10
-rw-r--r--src/userpref.h2
16 files changed, 504 insertions, 744 deletions
diff --git a/configure.ac b/configure.ac
index 286b1d8..9516ec4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -20,6 +20,7 @@ PKG_CHECK_MODULES(libglib2, glib-2.0 >= 2.14.1)
20PKG_CHECK_MODULES(libgthread2, gthread-2.0 >= 2.14.1) 20PKG_CHECK_MODULES(libgthread2, gthread-2.0 >= 2.14.1)
21PKG_CHECK_MODULES(libgnutls, gnutls >= 1.6.3 gnutls <= 2.5.0 ) 21PKG_CHECK_MODULES(libgnutls, gnutls >= 1.6.3 gnutls <= 2.5.0 )
22PKG_CHECK_MODULES(libtasn1, libtasn1 >= 1.1) 22PKG_CHECK_MODULES(libtasn1, libtasn1 >= 1.1)
23PKG_CHECK_MODULES(libplist, libplist-1.0 >= 0.1.0)
23 24
24# Checks for header files. 25# Checks for header files.
25AC_HEADER_STDC 26AC_HEADER_STDC
diff --git a/dev/Makefile.am b/dev/Makefile.am
index 4833728..d116581 100644
--- a/dev/Makefile.am
+++ b/dev/Makefile.am
@@ -16,4 +16,5 @@ lckd_client_LDADD = ../src/libiphone.la
16afccheck_SOURCES = afccheck.c 16afccheck_SOURCES = afccheck.c
17afccheck_CFLAGS = $(AM_CFLAGS) 17afccheck_CFLAGS = $(AM_CFLAGS)
18afccheck_LDFLAGS = $(AM_LDFLAGS) 18afccheck_LDFLAGS = $(AM_LDFLAGS)
19afccheck_LDADD = ../src/libiphone.la \ No newline at end of file 19afccheck_LDADD = ../src/libiphone.la
20
diff --git a/dev/lckdclient.c b/dev/lckdclient.c
index 96bc27d..c96f052 100644
--- a/dev/lckdclient.c
+++ b/dev/lckdclient.c
@@ -20,6 +20,7 @@
20 */ 20 */
21 21
22#include <stdio.h> 22#include <stdio.h>
23#include <stdlib.h>
23#include <string.h> 24#include <string.h>
24#include <glib.h> 25#include <glib.h>
25#include <readline/readline.h> 26#include <readline/readline.h>
diff --git a/dev/main.c b/dev/main.c
index 2dbfb4a..4974eef 100644
--- a/dev/main.c
+++ b/dev/main.c
@@ -87,7 +87,7 @@ int main(int argc, char *argv[])
87 iphone_afc_get_file_attr(afc, "/iTunesOnTheGoPlaylist.plist", &stbuf); 87 iphone_afc_get_file_attr(afc, "/iTunesOnTheGoPlaylist.plist", &stbuf);
88 if (IPHONE_E_SUCCESS == 88 if (IPHONE_E_SUCCESS ==
89 iphone_afc_open_file(afc, "/iTunesOnTheGoPlaylist.plist", IPHONE_AFC_FILE_READ, &my_file) && my_file) { 89 iphone_afc_open_file(afc, "/iTunesOnTheGoPlaylist.plist", IPHONE_AFC_FILE_READ, &my_file) && my_file) {
90 printf("A file size: %i\n", stbuf.st_size); 90 printf("A file size: %i\n", (int) stbuf.st_size);
91 char *file_data = (char *) malloc(sizeof(char) * stbuf.st_size); 91 char *file_data = (char *) malloc(sizeof(char) * stbuf.st_size);
92 iphone_afc_read_file(afc, my_file, file_data, stbuf.st_size, &bytes); 92 iphone_afc_read_file(afc, my_file, file_data, stbuf.st_size, &bytes);
93 if (bytes >= 0) { 93 if (bytes >= 0) {
diff --git a/src/AFC.c b/src/AFC.c
index 6027ed2..a1f7a08 100644
--- a/src/AFC.c
+++ b/src/AFC.c
@@ -21,8 +21,7 @@
21 21
22#include <stdio.h> 22#include <stdio.h>
23#include "AFC.h" 23#include "AFC.h"
24#include "plist.h" 24
25#include "utils.h"
26 25
27 26
28// This is the maximum size an AFC data packet can be 27// 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)
246 return retval; 245 return retval;
247 } 246 }
248 247
249 uint32 param1 = buffer[sizeof(AFCPacket)]; 248 uint32_t param1 = buffer[sizeof(AFCPacket)];
250 free(buffer); 249 free(buffer);
251 250
252 if (r_packet->operation == AFC_ERROR && !(client->afc_packet->operation == AFC_DELETE && param1 == 7)) { 251 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
475iphone_error_t iphone_afc_rename_file(iphone_afc_client_t client, const char *from, const char *to) 474iphone_error_t iphone_afc_rename_file(iphone_afc_client_t client, const char *from, const char *to)
476{ 475{
477 char *response = NULL; 476 char *response = NULL;
478 char *send = (char *) malloc(sizeof(char) * (strlen(from) + strlen(to) + 1 + sizeof(uint32))); 477 char *send = (char *) malloc(sizeof(char) * (strlen(from) + strlen(to) + 1 + sizeof(uint32_t)));
479 int bytes = 0; 478 int bytes = 0;
480 479
481 if (!client || !from || !to || !client->afc_packet || !client->connection) 480 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,
661 iphone_afc_file_mode_t file_mode, iphone_afc_file_t * file) 660 iphone_afc_file_mode_t file_mode, iphone_afc_file_t * file)
662{ 661{
663 iphone_afc_file_t file_loc = NULL; 662 iphone_afc_file_t file_loc = NULL;
664 uint32 ag = 0; 663 uint32_t ag = 0;
665 int bytes = 0, length = 0; 664 int bytes = 0, length = 0;
666 char *data = (char *) malloc(sizeof(char) * (8 + strlen(filename) + 1)); 665 char *data = (char *) malloc(sizeof(char) * (8 + strlen(filename) + 1));
667 666
@@ -796,8 +795,8 @@ iphone_afc_write_file(iphone_afc_client_t client, iphone_afc_file_t file,
796{ 795{
797 char *acknowledgement = NULL; 796 char *acknowledgement = NULL;
798 const int MAXIMUM_WRITE_SIZE = 1 << 15; 797 const int MAXIMUM_WRITE_SIZE = 1 << 15;
799 uint32 zero = 0, current_count = 0, i = 0; 798 uint32_t zero = 0, current_count = 0, i = 0;
800 uint32 segments = (length / MAXIMUM_WRITE_SIZE); 799 uint32_t segments = (length / MAXIMUM_WRITE_SIZE);
801 int bytes_loc = 0; 800 int bytes_loc = 0;
802 char *out_buffer = NULL; 801 char *out_buffer = NULL;
803 802
@@ -815,8 +814,8 @@ iphone_afc_write_file(iphone_afc_client_t client, iphone_afc_file_t file,
815 client->afc_packet->entire_length = client->afc_packet->this_length + MAXIMUM_WRITE_SIZE; 814 client->afc_packet->entire_length = client->afc_packet->this_length + MAXIMUM_WRITE_SIZE;
816 client->afc_packet->operation = AFC_WRITE; 815 client->afc_packet->operation = AFC_WRITE;
817 out_buffer = (char *) malloc(sizeof(char) * client->afc_packet->entire_length - sizeof(AFCPacket)); 816 out_buffer = (char *) malloc(sizeof(char) * client->afc_packet->entire_length - sizeof(AFCPacket));
818 memcpy(out_buffer, (char *) &file->filehandle, sizeof(uint32)); 817 memcpy(out_buffer, (char *) &file->filehandle, sizeof(uint32_t));
819 memcpy(out_buffer + 4, (char *) &zero, sizeof(uint32)); 818 memcpy(out_buffer + 4, (char *) &zero, sizeof(uint32_t));
820 memcpy(out_buffer + 8, data + current_count, MAXIMUM_WRITE_SIZE); 819 memcpy(out_buffer + 8, data + current_count, MAXIMUM_WRITE_SIZE);
821 bytes_loc = dispatch_AFC_packet(client, out_buffer, MAXIMUM_WRITE_SIZE + 8); 820 bytes_loc = dispatch_AFC_packet(client, out_buffer, MAXIMUM_WRITE_SIZE + 8);
822 if (bytes_loc < 0) { 821 if (bytes_loc < 0) {
@@ -848,8 +847,8 @@ iphone_afc_write_file(iphone_afc_client_t client, iphone_afc_file_t file,
848 client->afc_packet->entire_length = client->afc_packet->this_length + (length - current_count); 847 client->afc_packet->entire_length = client->afc_packet->this_length + (length - current_count);
849 client->afc_packet->operation = AFC_WRITE; 848 client->afc_packet->operation = AFC_WRITE;
850 out_buffer = (char *) malloc(sizeof(char) * client->afc_packet->entire_length - sizeof(AFCPacket)); 849 out_buffer = (char *) malloc(sizeof(char) * client->afc_packet->entire_length - sizeof(AFCPacket));
851 memcpy(out_buffer, (char *) &file->filehandle, sizeof(uint32)); 850 memcpy(out_buffer, (char *) &file->filehandle, sizeof(uint32_t));
852 memcpy(out_buffer + 4, (char *) &zero, sizeof(uint32)); 851 memcpy(out_buffer + 4, (char *) &zero, sizeof(uint32_t));
853 memcpy(out_buffer + 8, data + current_count, (length - current_count)); 852 memcpy(out_buffer + 8, data + current_count, (length - current_count));
854 bytes_loc = dispatch_AFC_packet(client, out_buffer, (length - current_count) + 8); 853 bytes_loc = dispatch_AFC_packet(client, out_buffer, (length - current_count) + 8);
855 free(out_buffer); 854 free(out_buffer);
@@ -884,7 +883,7 @@ iphone_error_t iphone_afc_close_file(iphone_afc_client_t client, iphone_afc_file
884 if (!client || !file) 883 if (!client || !file)
885 return IPHONE_E_INVALID_ARG; 884 return IPHONE_E_INVALID_ARG;
886 char *buffer = malloc(sizeof(char) * 8); 885 char *buffer = malloc(sizeof(char) * 8);
887 uint32 zero = 0; 886 uint32_t zero = 0;
888 int bytes = 0; 887 int bytes = 0;
889 888
890 afc_lock(client); 889 afc_lock(client);
@@ -892,8 +891,8 @@ iphone_error_t iphone_afc_close_file(iphone_afc_client_t client, iphone_afc_file
892 log_debug_msg("afc_close_file: File handle %i\n", file->filehandle); 891 log_debug_msg("afc_close_file: File handle %i\n", file->filehandle);
893 892
894 // Send command 893 // Send command
895 memcpy(buffer, &file->filehandle, sizeof(uint32)); 894 memcpy(buffer, &file->filehandle, sizeof(uint32_t));
896 memcpy(buffer + sizeof(uint32), &zero, sizeof(zero)); 895 memcpy(buffer + sizeof(uint32_t), &zero, sizeof(zero));
897 client->afc_packet->operation = AFC_FILE_CLOSE; 896 client->afc_packet->operation = AFC_FILE_CLOSE;
898 client->afc_packet->entire_length = client->afc_packet->this_length = 0; 897 client->afc_packet->entire_length = client->afc_packet->this_length = 0;
899 bytes = dispatch_AFC_packet(client, buffer, sizeof(char) * 8); 898 bytes = dispatch_AFC_packet(client, buffer, sizeof(char) * 8);
@@ -929,7 +928,7 @@ iphone_error_t iphone_afc_close_file(iphone_afc_client_t client, iphone_afc_file
929iphone_error_t iphone_afc_seek_file(iphone_afc_client_t client, iphone_afc_file_t file, int seekpos) 928iphone_error_t iphone_afc_seek_file(iphone_afc_client_t client, iphone_afc_file_t file, int seekpos)
930{ 929{
931 char *buffer = (char *) malloc(sizeof(char) * 24); 930 char *buffer = (char *) malloc(sizeof(char) * 24);
932 uint32 seekto = 0, zero = 0; 931 uint32_t seekto = 0, zero = 0;
933 int bytes = 0; 932 int bytes = 0;
934 933
935 if (seekpos < 0) 934 if (seekpos < 0)
@@ -939,12 +938,12 @@ iphone_error_t iphone_afc_seek_file(iphone_afc_client_t client, iphone_afc_file_
939 938
940 // Send the command 939 // Send the command
941 seekto = seekpos; 940 seekto = seekpos;
942 memcpy(buffer, &file->filehandle, sizeof(uint32)); // handle 941 memcpy(buffer, &file->filehandle, sizeof(uint32_t)); // handle
943 memcpy(buffer + 4, &zero, sizeof(uint32)); // pad 942 memcpy(buffer + 4, &zero, sizeof(uint32_t)); // pad
944 memcpy(buffer + 8, &zero, sizeof(uint32)); // fromwhere 943 memcpy(buffer + 8, &zero, sizeof(uint32_t)); // fromwhere
945 memcpy(buffer + 12, &zero, sizeof(uint32)); // pad 944 memcpy(buffer + 12, &zero, sizeof(uint32_t)); // pad
946 memcpy(buffer + 16, &seekto, sizeof(uint32)); // offset 945 memcpy(buffer + 16, &seekto, sizeof(uint32_t)); // offset
947 memcpy(buffer + 20, &zero, sizeof(uint32)); // pad 946 memcpy(buffer + 20, &zero, sizeof(uint32_t)); // pad
948 client->afc_packet->operation = AFC_FILE_SEEK; 947 client->afc_packet->operation = AFC_FILE_SEEK;
949 client->afc_packet->this_length = client->afc_packet->entire_length = 0; 948 client->afc_packet->this_length = client->afc_packet->entire_length = 0;
950 bytes = dispatch_AFC_packet(client, buffer, 23); 949 bytes = dispatch_AFC_packet(client, buffer, 23);
@@ -984,14 +983,14 @@ iphone_error_t iphone_afc_truncate_file(iphone_afc_client_t client, iphone_afc_f
984{ 983{
985 char *buffer = (char *) malloc(sizeof(char) * 16); 984 char *buffer = (char *) malloc(sizeof(char) * 16);
986 int bytes = 0; 985 int bytes = 0;
987 uint32 zero = 0; 986 uint32_t zero = 0;
988 987
989 afc_lock(client); 988 afc_lock(client);
990 989
991 // Send command 990 // Send command
992 memcpy(buffer, &file->filehandle, sizeof(uint32)); // handle 991 memcpy(buffer, &file->filehandle, sizeof(uint32_t)); // handle
993 memcpy(buffer + 4, &zero, sizeof(uint32)); // pad 992 memcpy(buffer + 4, &zero, sizeof(uint32_t)); // pad
994 memcpy(buffer + 8, &newsize, sizeof(uint32)); // newsize 993 memcpy(buffer + 8, &newsize, sizeof(uint32_t)); // newsize
995 memcpy(buffer + 12, &zero, 3); // pad 994 memcpy(buffer + 12, &zero, 3); // pad
996 client->afc_packet->operation = AFC_FILE_TRUNCATE; 995 client->afc_packet->operation = AFC_FILE_TRUNCATE;
997 client->afc_packet->this_length = client->afc_packet->entire_length = 0; 996 client->afc_packet->this_length = client->afc_packet->entire_length = 0;
@@ -1017,7 +1016,7 @@ iphone_error_t iphone_afc_truncate_file(iphone_afc_client_t client, iphone_afc_f
1017 } 1016 }
1018} 1017}
1019 1018
1020uint32 iphone_afc_get_file_handle(iphone_afc_file_t file) 1019uint32_t iphone_afc_get_file_handle(iphone_afc_file_t file)
1021{ 1020{
1022 return file->filehandle; 1021 return file->filehandle;
1023} 1022}
diff --git a/src/AFC.h b/src/AFC.h
index 463c13e..5e4d17c 100644
--- a/src/AFC.h
+++ b/src/AFC.h
@@ -29,12 +29,12 @@
29#include <glib.h> 29#include <glib.h>
30 30
31typedef struct { 31typedef struct {
32 uint32 header1, header2; 32 uint32_t header1, header2;
33 uint32 entire_length, unknown1, this_length, unknown2, packet_num, unknown3, operation, unknown4; 33 uint32_t entire_length, unknown1, this_length, unknown2, packet_num, unknown3, operation, unknown4;
34} AFCPacket; 34} AFCPacket;
35 35
36typedef struct { 36typedef struct {
37 uint32 filehandle, unknown1, size, unknown2; 37 uint32_t filehandle, unknown1, size, unknown2;
38} AFCFilePacket; 38} AFCFilePacket;
39 39
40typedef struct __AFCToken { 40typedef struct __AFCToken {
@@ -51,7 +51,7 @@ struct iphone_afc_client_int {
51}; 51};
52 52
53struct iphone_afc_file_int { 53struct iphone_afc_file_int {
54 uint32 filehandle, blocks, size, type; 54 uint32_t filehandle, blocks, size, type;
55}; 55};
56 56
57 57
@@ -74,4 +74,4 @@ enum {
74 AFC_WRITE = 0x00000010 74 AFC_WRITE = 0x00000010
75}; 75};
76 76
77uint32 iphone_afc_get_file_handle(iphone_afc_file_t file); 77uint32_t iphone_afc_get_file_handle(iphone_afc_file_t file);
diff --git a/src/Makefile.am b/src/Makefile.am
index 785aacf..2514367 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,15 +1,15 @@
1INCLUDES = -I$(top_srcdir)/include 1INCLUDES = -I$(top_srcdir)/include
2 2
3AM_CFLAGS = $(libxml2_CFLAGS) $(libusb_CFLAGS) $(libglib2_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(libgthread2_CFLAGS) -g 3AM_CFLAGS = $(libxml2_CFLAGS) $(libusb_CFLAGS) $(libglib2_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(libgthread2_CFLAGS) $(libplist_CFLAGS) -g
4AM_LDFLAGS = $(libxml2_LIBS) $(libusb_LIBS) $(libglib2_LIBS) $(libgnutls_LIBS) $(libtasn1_LIBS) $(libgthread2_LIBS) 4AM_LDFLAGS = $(libxml2_LIBS) $(libusb_LIBS) $(libglib2_LIBS) $(libgnutls_LIBS) $(libtasn1_LIBS) $(libgthread2_LIBS) $(libplist_LIBS)
5 5
6bin_PROGRAMS = libiphone-initconf 6bin_PROGRAMS = libiphone-initconf
7 7
8 8
9libiphone_initconf_SOURCES = initconf.c userpref.c lockdown.c plist.c usbmux.c iphone.c utils.c 9libiphone_initconf_SOURCES = initconf.c userpref.c utils.c
10libiphone_initconf_CFLAGS = $(libgthread2_CFLAGS) $(AM_CFLAGS) 10libiphone_initconf_CFLAGS = $(libgthread2_CFLAGS) $(AM_CFLAGS)
11libiphone_initconf_LDFLAGS = $(libgthread2_LIBS) $(AM_LDFLAGS) 11libiphone_initconf_LDFLAGS = $(libgthread2_LIBS) $(AM_LDFLAGS)
12 12
13 13
14lib_LTLIBRARIES = libiphone.la 14lib_LTLIBRARIES = libiphone.la
15libiphone_la_SOURCES = usbmux.c iphone.c plist.c lockdown.c AFC.c userpref.c utils.c 15libiphone_la_SOURCES = usbmux.c iphone.c lockdown.c AFC.c userpref.c utils.c
diff --git a/src/initconf.c b/src/initconf.c
index 205c97a..538f344 100644
--- a/src/initconf.c
+++ b/src/initconf.c
@@ -28,7 +28,6 @@
28 28
29#include "libiphone/libiphone.h" 29#include "libiphone/libiphone.h"
30#include "userpref.h" 30#include "userpref.h"
31#include "lockdown.h"
32#include "utils.h" 31#include "utils.h"
33 32
34/** Generates a 2048 byte key, split into a function so that it can be run in a 33/** Generates a 2048 byte key, split into a function so that it can be run in a
@@ -60,6 +59,35 @@ static void progress_bar(gpointer mutex)
60 g_thread_exit(0); 59 g_thread_exit(0);
61} 60}
62 61
62int get_rand(int min, int max)
63{
64 int retval = (rand() % (max - min)) + min;
65 return retval;
66}
67
68/** Generates a valid HostID (which is actually a UUID).
69 *
70 * @param A null terminated string containing a valid HostID.
71 */
72char *lockdownd_generate_hostid()
73{
74 char *hostid = (char *) malloc(sizeof(char) * 37); // HostID's are just UUID's, and UUID's are 36 characters long
75 const char *chars = "ABCDEF0123456789";
76 srand(time(NULL));
77 int i = 0;
78
79 for (i = 0; i < 36; i++) {
80 if (i == 8 || i == 13 || i == 18 || i == 23) {
81 hostid[i] = '-';
82 continue;
83 } else {
84 hostid[i] = chars[get_rand(0, 16)];
85 }
86 }
87 hostid[36] = '\0'; // make it a real string
88 return hostid;
89}
90
63int main(int argc, char *argv[]) 91int main(int argc, char *argv[])
64{ 92{
65 GThread *progress_thread, *key_thread; 93 GThread *progress_thread, *key_thread;
diff --git a/src/lockdown.c b/src/lockdown.c
index ab168a3..872b7b0 100644
--- a/src/lockdown.c
+++ b/src/lockdown.c
@@ -31,6 +31,8 @@
31#include <libtasn1.h> 31#include <libtasn1.h>
32#include <gnutls/x509.h> 32#include <gnutls/x509.h>
33 33
34#include <plist/plist.h>
35
34const ASN1_ARRAY_TYPE pkcs1_asn1_tab[] = { 36const ASN1_ARRAY_TYPE pkcs1_asn1_tab[] = {
35 {"PKCS1", 536872976, 0}, 37 {"PKCS1", 536872976, 0},
36 {0, 1073741836, 0}, 38 {0, 1073741836, 0},
@@ -40,35 +42,6 @@ const ASN1_ARRAY_TYPE pkcs1_asn1_tab[] = {
40 {0, 0, 0} 42 {0, 0, 0}
41}; 43};
42 44
43static int get_rand(int min, int max)
44{
45 int retval = (rand() % (max - min)) + min;
46 return retval;
47}
48
49/** Generates a valid HostID (which is actually a UUID).
50 *
51 * @param A null terminated string containing a valid HostID.
52 */
53char *lockdownd_generate_hostid(void)
54{
55 char *hostid = (char *) malloc(sizeof(char) * 37); // HostID's are just UUID's, and UUID's are 36 characters long
56 const char *chars = "ABCDEF0123456789";
57 srand(time(NULL));
58 int i = 0;
59
60 for (i = 0; i < 36; i++) {
61 if (i == 8 || i == 13 || i == 18 || i == 23) {
62 hostid[i] = '-';
63 continue;
64 } else {
65 hostid[i] = chars[get_rand(0, 16)];
66 }
67 }
68 hostid[36] = '\0'; // make it a real string
69 return hostid;
70}
71
72/** Creates a lockdownd client for the give iPhone. 45/** Creates a lockdownd client for the give iPhone.
73 * 46 *
74 * @param phone The iPhone to create a lockdownd client for 47 * @param phone The iPhone to create a lockdownd client for
@@ -101,59 +74,64 @@ iphone_lckd_client_t new_lockdownd_client(iphone_device_t phone)
101static void iphone_lckd_stop_session(iphone_lckd_client_t control) 74static void iphone_lckd_stop_session(iphone_lckd_client_t control)
102{ 75{
103 if (!control) 76 if (!control)
104 return; // IPHONE_E_INVALID_ARG; 77 return; //IPHONE_E_INVALID_ARG;
105 xmlDocPtr plist = new_plist(); 78
106 xmlNode *dict, *key;
107 char **dictionary;
108 int bytes = 0, i = 0; 79 int bytes = 0, i = 0;
109 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; 80 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
110 81
111 log_debug_msg("lockdownd_stop_session() called\n"); 82 plist_t dict = plist_new_dict();
112 dict = add_child_to_plist(plist, "dict", "\n", NULL, 0); 83 plist_add_sub_element(dict, PLIST_KEY, (void *) "Request", strlen("Request"));
113 key = add_key_str_dict_element(plist, dict, "Request", "StopSession", 1); 84 plist_add_sub_element(dict, PLIST_STRING, (void *) "StopSession", strlen("StopSession"));
114 key = add_key_str_dict_element(plist, dict, "SessionID", control->session_id, 1); 85 plist_add_sub_element(dict, PLIST_KEY, (void *) "SessionID", strlen("SessionID"));
86 plist_add_sub_element(dict, PLIST_STRING, (void *) control->session_id, strlen(control->session_id));
115 87
116 char *XML_content; 88 log_debug_msg("iphone_lckd_stop_session() called\n");
117 uint32 length; 89 char *XML_content = NULL;
90 uint32_t length = 0;
118 91
119 xmlDocDumpMemory(plist, (xmlChar **) & XML_content, &length); 92 plist_to_xml(dict, &XML_content, &length);
93 log_debug_msg("Send msg :\nsize : %i\nxml : %s", length, XML_content);
120 ret = iphone_lckd_send(control, XML_content, length, &bytes); 94 ret = iphone_lckd_send(control, XML_content, length, &bytes);
121 95
122 xmlFree(XML_content); 96 free(XML_content);
123 xmlFreeDoc(plist); 97 XML_content = NULL;
124 plist = NULL; 98 plist_free(dict);
99 dict = NULL;
100
125 ret = iphone_lckd_recv(control, &XML_content, &bytes); 101 ret = iphone_lckd_recv(control, &XML_content, &bytes);
102 log_debug_msg("Receive msg :\nsize : %i\nxml : %s", bytes, XML_content);
103 plist_from_xml(XML_content, bytes, &dict);
126 104
127 plist = xmlReadMemory(XML_content, bytes, NULL, NULL, 0);
128 if (!plist) {
129 fprintf(stderr, "lockdownd_stop_session(): IPHONE_E_PLIST_ERROR\n");
130 return; //IPHONE_E_PLIST_ERROR;
131 }
132 dict = xmlDocGetRootElement(plist);
133 for (dict = dict->children; dict; dict = dict->next) {
134 if (!xmlStrcmp(dict->name, "dict"))
135 break;
136 }
137 if (!dict) { 105 if (!dict) {
138 fprintf(stderr, "lockdownd_stop_session(): IPHONE_E_DICT_ERROR\n"); 106 log_debug_msg("lockdownd_stop_session(): IPHONE_E_PLIST_ERROR\n");
139 return; //IPHONE_E_DICT_ERROR; 107 return; // IPHONE_E_PLIST_ERROR;
140 } 108 }
141 dictionary = read_dict_element_strings(dict);
142 xmlFreeDoc(plist);
143 free(XML_content);
144 109
145 for (i = 0; dictionary[i]; i += 2) { 110 plist_t query_node = plist_find_node(dict, PLIST_STRING, "StopSession", strlen("StopSession"));
146 if (!strcmp(dictionary[i], "Result") && !strcmp(dictionary[i + 1], "Success")) { 111 plist_t result_node = plist_get_next_sibling(query_node);
147 log_debug_msg("lockdownd_stop_session(): success\n"); 112 plist_t value_node = plist_get_next_sibling(result_node);
148 ret = IPHONE_E_SUCCESS; 113
149 break; 114 plist_type result_type;
150 } 115 plist_type value_type;
116
117 char *result_value = NULL;
118 char *value_value = NULL;
119 uint64_t result_length = 0;
120 uint64_t value_length = 0;
121
122 plist_get_type_and_value(result_node, &result_type, (void *) (&result_value), &result_length);
123 plist_get_type_and_value(value_node, &value_type, (void *) (&value_value), &value_length);
124
125 if (result_type == PLIST_KEY &&
126 value_type == PLIST_STRING && !strcmp(result_value, "Result") && !strcmp(value_value, "Success")) {
127 log_debug_msg("lockdownd_stop_session(): success\n");
128 ret = IPHONE_E_SUCCESS;
151 } 129 }
152 130
153 free_dictionary(dictionary); 131 return; // ret;
154 return; //ret;
155} 132}
156 133
134
157/** 135/**
158 * Shuts down the SSL session by first calling iphone_lckd_stop_session 136 * Shuts down the SSL session by first calling iphone_lckd_stop_session
159 * to cleanly close the lockdownd communication session, and then 137 * to cleanly close the lockdownd communication session, and then
@@ -184,6 +162,7 @@ static void iphone_lckd_stop_SSL_session(iphone_lckd_client_t client)
184 return; 162 return;
185} 163}
186 164
165
187/** Closes the lockdownd client and does the necessary housekeeping. 166/** Closes the lockdownd client and does the necessary housekeeping.
188 * 167 *
189 * @param control The lockdown client 168 * @param control The lockdown client
@@ -223,7 +202,7 @@ iphone_error_t iphone_lckd_recv(iphone_lckd_client_t client, char **dump_data, u
223 return IPHONE_E_INVALID_ARG; 202 return IPHONE_E_INVALID_ARG;
224 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; 203 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
225 char *receive; 204 char *receive;
226 uint32 datalen = 0, bytes = 0; 205 uint32_t datalen = 0, bytes = 0;
227 206
228 if (!client->in_SSL) 207 if (!client->in_SSL)
229 ret = iphone_mux_recv(client->connection, (char *) &datalen, sizeof(datalen), &bytes); 208 ret = iphone_mux_recv(client->connection, (char *) &datalen, sizeof(datalen), &bytes);
@@ -297,49 +276,55 @@ iphone_error_t lockdownd_hello(iphone_lckd_client_t control)
297{ 276{
298 if (!control) 277 if (!control)
299 return IPHONE_E_INVALID_ARG; 278 return IPHONE_E_INVALID_ARG;
300 xmlDocPtr plist = new_plist(); 279
301 xmlNode *dict, *key;
302 char **dictionary;
303 int bytes = 0, i = 0; 280 int bytes = 0, i = 0;
304 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; 281 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
305 282
283 plist_t dict = plist_new_dict();
284 plist_add_sub_element(dict, PLIST_KEY, (void *) "Request", strlen("Request"));
285 plist_add_sub_element(dict, PLIST_STRING, (void *) "QueryType", strlen("QueryType"));
286
306 log_debug_msg("lockdownd_hello() called\n"); 287 log_debug_msg("lockdownd_hello() called\n");
307 dict = add_child_to_plist(plist, "dict", "\n", NULL, 0); 288 char *XML_content = NULL;
308 key = add_key_str_dict_element(plist, dict, "Request", "QueryType", 1); 289 uint32_t length = 0;
309 char *XML_content;
310 uint32 length;
311 290
312 xmlDocDumpMemory(plist, (xmlChar **) & XML_content, &length); 291 plist_to_xml(dict, &XML_content, &length);
292 log_debug_msg("Send msg :\nsize : %i\nxml : %s", length, XML_content);
313 ret = iphone_lckd_send(control, XML_content, length, &bytes); 293 ret = iphone_lckd_send(control, XML_content, length, &bytes);
314 294
315 xmlFree(XML_content); 295 free(XML_content);
316 xmlFreeDoc(plist); 296 XML_content = NULL;
317 plist = NULL; 297 plist_free(dict);
298 dict = NULL;
299
318 ret = iphone_lckd_recv(control, &XML_content, &bytes); 300 ret = iphone_lckd_recv(control, &XML_content, &bytes);
301 log_debug_msg("Receive msg :\nsize : %i\nxml : %s", bytes, XML_content);
302 plist_from_xml(XML_content, bytes, &dict);
319 303
320 plist = xmlReadMemory(XML_content, bytes, NULL, NULL, 0);
321 if (!plist)
322 return IPHONE_E_PLIST_ERROR;
323 dict = xmlDocGetRootElement(plist);
324 for (dict = dict->children; dict; dict = dict->next) {
325 if (!xmlStrcmp(dict->name, "dict"))
326 break;
327 }
328 if (!dict) 304 if (!dict)
329 return IPHONE_E_DICT_ERROR; 305 return IPHONE_E_PLIST_ERROR;
330 dictionary = read_dict_element_strings(dict);
331 xmlFreeDoc(plist);
332 free(XML_content);
333 306
334 for (i = 0; dictionary[i]; i += 2) { 307 plist_t query_node = plist_find_node(dict, PLIST_STRING, "QueryType", strlen("QueryType"));
335 if (!strcmp(dictionary[i], "Result") && !strcmp(dictionary[i + 1], "Success")) { 308 plist_t result_node = plist_get_next_sibling(query_node);
336 log_debug_msg("lockdownd_hello(): success\n"); 309 plist_t value_node = plist_get_next_sibling(result_node);
337 ret = IPHONE_E_SUCCESS; 310
338 break; 311 plist_type result_type;
339 } 312 plist_type value_type;
313
314 char *result_value = NULL;
315 char *value_value = NULL;
316 uint64_t result_length = 0;
317 uint64_t value_length = 0;
318
319 plist_get_type_and_value(result_node, &result_type, (void *) (&result_value), &result_length);
320 plist_get_type_and_value(value_node, &value_type, (void *) (&value_value), &value_length);
321
322 if (result_type == PLIST_KEY &&
323 value_type == PLIST_STRING && !strcmp(result_value, "Result") && !strcmp(value_value, "Success")) {
324 log_debug_msg("lockdownd_hello(): success\n");
325 ret = IPHONE_E_SUCCESS;
340 } 326 }
341 327
342 free_dictionary(dictionary);
343 return ret; 328 return ret;
344} 329}
345 330
@@ -351,74 +336,94 @@ iphone_error_t lockdownd_hello(iphone_lckd_client_t control)
351 * 336 *
352 * @return IPHONE_E_SUCCESS on success. 337 * @return IPHONE_E_SUCCESS on success.
353 */ 338 */
354iphone_error_t lockdownd_generic_get_value(iphone_lckd_client_t control, const char *req_key, const char *req_string, 339iphone_error_t lockdownd_generic_get_value(iphone_lckd_client_t control, const char *req_key, char *req_string,
355 char **value) 340 gnutls_datum_t * value)
356{ 341{
357 if (!control || !req_key || !value || (value && *value)) 342 if (!control || !req_key || !value || value->data)
358 return IPHONE_E_INVALID_ARG; 343 return IPHONE_E_INVALID_ARG;
359 xmlDocPtr plist = new_plist(); 344
360 xmlNode *dict = NULL; 345 plist_t dict = NULL;
361 xmlNode *key = NULL;;
362 char **dictionary = NULL;
363 int bytes = 0, i = 0; 346 int bytes = 0, i = 0;
364 char *XML_content = NULL; 347 char *XML_content = NULL;
365 uint32 length = 0; 348 uint32_t length = 0;
366 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; 349 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
367 350
368 /* Setup DevicePublicKey request plist */ 351 /* Setup DevicePublicKey request plist */
369 dict = add_child_to_plist(plist, "dict", "\n", NULL, 0); 352 dict = plist_new_dict();
370 key = add_key_str_dict_element(plist, dict, req_key, req_string, 1); 353 plist_add_sub_element(dict, PLIST_KEY, (void *) req_key, strlen(req_key));
371 key = add_key_str_dict_element(plist, dict, "Request", "GetValue", 1); 354 plist_add_sub_element(dict, PLIST_STRING, (void *) req_string, strlen(req_string));
372 xmlDocDumpMemory(plist, (xmlChar **) & XML_content, &length); 355 plist_add_sub_element(dict, PLIST_KEY, (void *) "Request", strlen("Request"));
356 plist_add_sub_element(dict, PLIST_STRING, (void *) "GetValue", strlen("GetValue"));
357 plist_to_xml(dict, &XML_content, &length);
373 358
374 /* send to iPhone */ 359 /* send to iPhone */
360 log_debug_msg("Send msg :\nsize : %i\nxml : %s", length, XML_content);
375 ret = iphone_lckd_send(control, XML_content, length, &bytes); 361 ret = iphone_lckd_send(control, XML_content, length, &bytes);
376 362
377 xmlFree(XML_content); 363 free(XML_content);
378 xmlFreeDoc(plist); 364 XML_content = NULL;
379 plist = NULL; 365 plist_free(dict);
366 dict = NULL;
380 367
381 if (ret != IPHONE_E_SUCCESS) 368 if (ret != IPHONE_E_SUCCESS)
382 return ret; 369 return ret;
383 370
384 /* Now get iPhone's answer */ 371 /* Now get iPhone's answer */
385 ret = iphone_lckd_recv(control, &XML_content, &bytes); 372 ret = iphone_lckd_recv(control, &XML_content, &bytes);
373 log_debug_msg("Receive msg :\nsize : %i\nxml : %s", bytes, XML_content);
386 374
387 if (ret != IPHONE_E_SUCCESS) 375 if (ret != IPHONE_E_SUCCESS)
388 return ret; 376 return ret;
389 377
390 plist = xmlReadMemory(XML_content, bytes, NULL, NULL, 0); 378 plist_from_xml(XML_content, bytes, &dict);
391 if (!plist)
392 return IPHONE_E_PLIST_ERROR;
393 dict = xmlDocGetRootElement(plist);
394 for (dict = dict->children; dict; dict = dict->next) {
395 if (!xmlStrcmp(dict->name, "dict"))
396 break;
397 }
398 if (!dict) 379 if (!dict)
399 return IPHONE_E_DICT_ERROR; 380 return IPHONE_E_PLIST_ERROR;
400 381
401 /* Parse xml to check success and to find public key */ 382 plist_t query_node = plist_find_node(dict, PLIST_STRING, "GetValue", strlen("GetValue"));
402 dictionary = read_dict_element_strings(dict); 383 plist_t result_key_node = plist_get_next_sibling(query_node);
403 xmlFreeDoc(plist); 384 plist_t result_value_node = plist_get_next_sibling(result_key_node);
404 free(XML_content);
405 385
406 int success = 0; 386 plist_type result_key_type;
407 for (i = 0; dictionary[i]; i += 2) { 387 plist_type result_value_type;
408 if (!strcmp(dictionary[i], "Result") && !strcmp(dictionary[i + 1], "Success")) { 388 char *result_key = NULL;
409 success = 1; 389 char *result_value = NULL;
410 } 390 uint64_t result_length = 0;
411 if (!strcmp(dictionary[i], "Value")) { 391 uint64_t value_length = 0;
412 *value = strdup(dictionary[i + 1]); 392
413 } 393 plist_get_type_and_value(result_key_node, &result_key_type, (void *) (&result_key), &result_length);
394 plist_get_type_and_value(result_value_node, &result_value_type, (void *) (&result_value), &value_length);
395
396 if (result_key_type == PLIST_KEY &&
397 result_value_type == PLIST_STRING && !strcmp(result_key, "Result") && !strcmp(result_value, "Success")) {
398 log_debug_msg("lockdownd_generic_get_value(): success\n");
399 ret = IPHONE_E_SUCCESS;
414 } 400 }
415 401
416 if (dictionary) { 402 if (ret != IPHONE_E_SUCCESS) {
417 free_dictionary(dictionary); 403 return IPHONE_E_DICT_ERROR;
418 dictionary = NULL;
419 } 404 }
420 if (success) 405
406 plist_t value_key_node = plist_get_next_sibling(result_key_node);
407 plist_t value_value_node = plist_get_next_sibling(value_key_node);
408 plist_type value_key_type;
409 plist_type value_value_type;
410 char *value_key = NULL;
411 char *value_value = NULL;
412 uint64_t key_length = 0;
413 uint64_t valval_length = 0;
414
415 plist_get_type_and_value(value_key_node, &value_key_type, (void *) (&value_key), &key_length);
416 plist_get_type_and_value(value_value_node, &value_value_type, (void *) (&value_value), &valval_length);
417
418 if (value_key_type == PLIST_KEY && !strcmp(result_key, "Value")) {
419 log_debug_msg("lockdownd_generic_get_value(): success\n");
420 value->data = value_value;
421 value->size = valval_length;
421 ret = IPHONE_E_SUCCESS; 422 ret = IPHONE_E_SUCCESS;
423 }
424
425 plist_free(dict);
426 free(XML_content);
422 return ret; 427 return ret;
423} 428}
424 429
@@ -430,7 +435,9 @@ iphone_error_t lockdownd_generic_get_value(iphone_lckd_client_t control, const c
430 */ 435 */
431iphone_error_t lockdownd_get_device_uid(iphone_lckd_client_t control, char **uid) 436iphone_error_t lockdownd_get_device_uid(iphone_lckd_client_t control, char **uid)
432{ 437{
433 return lockdownd_generic_get_value(control, "Key", "UniqueDeviceID", uid); 438 gnutls_datum_t temp = { NULL, 0 };
439 return lockdownd_generic_get_value(control, "Key", "UniqueDeviceID", &temp);
440 *uid = temp.data;
434} 441}
435 442
436/** Askes for the device's public key. Part of the lockdownd handshake. 443/** Askes for the device's public key. Part of the lockdownd handshake.
@@ -439,7 +446,7 @@ iphone_error_t lockdownd_get_device_uid(iphone_lckd_client_t control, char **uid
439 * 446 *
440 * @return 1 on success and 0 on failure. 447 * @return 1 on success and 0 on failure.
441 */ 448 */
442iphone_error_t lockdownd_get_device_public_key(iphone_lckd_client_t control, char **public_key) 449iphone_error_t lockdownd_get_device_public_key(iphone_lckd_client_t control, gnutls_datum_t * public_key)
443{ 450{
444 return lockdownd_generic_get_value(control, "Key", "DevicePublicKey", public_key); 451 return lockdownd_generic_get_value(control, "Key", "DevicePublicKey", public_key);
445} 452}
@@ -511,51 +518,52 @@ iphone_error_t iphone_lckd_new_client(iphone_device_t device, iphone_lckd_client
511iphone_error_t lockdownd_pair_device(iphone_lckd_client_t control, char *uid, char *host_id) 518iphone_error_t lockdownd_pair_device(iphone_lckd_client_t control, char *uid, char *host_id)
512{ 519{
513 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; 520 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
514 xmlDocPtr plist = new_plist(); 521 plist_t dict = NULL;
515 xmlNode *dict = NULL; 522 plist_t dict_record = NULL;
516 xmlNode *dictRecord = NULL;
517 char **dictionary = NULL;
518 int bytes = 0, i = 0; 523 int bytes = 0, i = 0;
519 char *XML_content = NULL; 524 char *XML_content = NULL;
520 uint32 length = 0; 525 uint32_t length = 0;
521 526
522 char *device_cert_b64 = NULL; 527 gnutls_datum_t device_cert = { NULL, 0 };
523 char *host_cert_b64 = NULL; 528 gnutls_datum_t host_cert = { NULL, 0 };
524 char *root_cert_b64 = NULL; 529 gnutls_datum_t root_cert = { NULL, 0 };
525 char *public_key_b64 = NULL; 530 gnutls_datum_t public_key = { NULL, 0 };
526 531
527 ret = lockdownd_get_device_public_key(control, &public_key_b64); 532 ret = lockdownd_get_device_public_key(control, &public_key);
528 if (ret != IPHONE_E_SUCCESS) { 533 if (ret != IPHONE_E_SUCCESS) {
529 fprintf(stderr, "Device refused to send public key.\n"); 534 fprintf(stderr, "Device refused to send public key.\n");
530 return ret; 535 return ret;
531 } 536 }
532 537
533 ret = lockdownd_gen_pair_cert(public_key_b64, &device_cert_b64, &host_cert_b64, &root_cert_b64); 538 ret = lockdownd_gen_pair_cert(public_key, &device_cert, &host_cert, &root_cert);
534 if (ret != IPHONE_E_SUCCESS) { 539 if (ret != IPHONE_E_SUCCESS) {
535 free(public_key_b64); 540 free(public_key.data);
536 return ret; 541 return ret;
537 } 542 }
538 543
539 /* Setup Pair request plist */ 544 /* Setup Pair request plist */
540 dict = add_child_to_plist(plist, "dict", "\n", NULL, 0); 545 dict = plist_new_dict();
541 dictRecord = add_key_dict_node(plist, dict, "PairRecord", "\n", 1); 546 plist_add_sub_element(dict, PLIST_KEY, (void *) "PairRecord", strlen("PairRecord"));
542 //dictRecord = add_child_to_plist(plist, "dict", "\n", NULL, 1); 547 dict_record = plist_add_sub_element(dict, PLIST_DICT, NULL, 0);
543 add_key_data_dict_element(plist, dictRecord, "DeviceCertificate", device_cert_b64, 2); 548 plist_add_sub_element(dict_record, PLIST_KEY, (void *) "DeviceCertificate", strlen("DeviceCertificate"));
544 add_key_data_dict_element(plist, dictRecord, "HostCertificate", host_cert_b64, 2); 549 plist_add_sub_element(dict_record, PLIST_DATA, (void *) device_cert.data, device_cert.size);
545 add_key_str_dict_element(plist, dictRecord, "HostID", host_id, 2); 550 plist_add_sub_element(dict_record, PLIST_KEY, (void *) "HostCertificate", strlen("HostCertificate"));
546 add_key_data_dict_element(plist, dictRecord, "RootCertificate", root_cert_b64, 2); 551 plist_add_sub_element(dict_record, PLIST_DATA, (void *) host_cert.data, host_cert.size);
547 add_key_str_dict_element(plist, dict, "Request", "Pair", 1); 552 plist_add_sub_element(dict_record, PLIST_KEY, (void *) "HostID", strlen("HostID"));
548 553 plist_add_sub_element(dict_record, PLIST_STRING, (void *) host_id, strlen(host_id));
549 xmlDocDumpMemory(plist, (xmlChar **) & XML_content, &length); 554 plist_add_sub_element(dict_record, PLIST_KEY, (void *) "RootCertificate", strlen("RootCertificate"));
550 555 plist_add_sub_element(dict_record, PLIST_DATA, (void *) root_cert.data, root_cert.size);
551 printf("XML Pairing request : %s\n", XML_content); 556 plist_add_sub_element(dict_record, PLIST_KEY, (void *) "Request", strlen("Request"));
557 plist_add_sub_element(dict_record, PLIST_STRING, (void *) "Pair", strlen("Pair"));
558 plist_to_xml(dict, &XML_content, &length);
559 log_debug_msg("XML Pairing request :\nsize : %i\nxml :\n %s", length, XML_content);
552 560
553 /* send to iPhone */ 561 /* send to iPhone */
554 ret = iphone_lckd_send(control, XML_content, length, &bytes); 562 ret = iphone_lckd_send(control, XML_content, length, &bytes);
555 563
556 xmlFree(XML_content); 564 free(XML_content);
557 xmlFreeDoc(plist); 565 plist_free(dict);
558 plist = NULL; 566 dict = NULL;
559 567
560 if (ret != IPHONE_E_SUCCESS) 568 if (ret != IPHONE_E_SUCCESS)
561 return ret; 569 return ret;
@@ -570,48 +578,39 @@ iphone_error_t lockdownd_pair_device(iphone_lckd_client_t control, char *uid, ch
570 log_debug_msg(XML_content); 578 log_debug_msg(XML_content);
571 log_debug_msg("\n\n"); 579 log_debug_msg("\n\n");
572 580
573 plist = xmlReadMemory(XML_content, bytes, NULL, NULL, 0); 581 plist_from_xml(XML_content, bytes, &dict);
574 if (!plist) { 582 if (!dict)
575 free(public_key_b64);
576 return IPHONE_E_PLIST_ERROR; 583 return IPHONE_E_PLIST_ERROR;
577 }
578 dict = xmlDocGetRootElement(plist);
579 for (dict = dict->children; dict; dict = dict->next) {
580 if (!xmlStrcmp(dict->name, "dict"))
581 break;
582 }
583 if (!dict) {
584 free(public_key_b64);
585 return IPHONE_E_DICT_ERROR;
586 }
587 584
588 /* Parse xml to check success and to find public key */ 585 plist_t query_node = plist_find_node(dict, PLIST_STRING, "Pair", strlen("Pair"));
589 dictionary = read_dict_element_strings(dict); 586 plist_t result_key_node = plist_get_next_sibling(query_node);
590 xmlFreeDoc(plist); 587 plist_t result_value_node = plist_get_next_sibling(result_key_node);
591 free(XML_content);
592 588
593 int success = 0; 589 plist_type result_key_type;
594 for (i = 0; dictionary[i]; i += 2) { 590 plist_type result_value_type;
595 if (!strcmp(dictionary[i], "Result") && !strcmp(dictionary[i + 1], "Success")) { 591 char *result_key = NULL;
596 success = 1; 592 char *result_value = NULL;
597 } 593 uint64_t key_length = 0;
598 } 594 uint64_t val_length = 0;
599 595
600 if (dictionary) { 596 plist_get_type_and_value(result_key_node, &result_key_type, (void *) (&result_key), &key_length);
601 free_dictionary(dictionary); 597 plist_get_type_and_value(result_value_node, &result_value_type, (void *) (&result_value), &val_length);
602 dictionary = NULL; 598
599 if (result_key_type == PLIST_KEY &&
600 result_value_type == PLIST_STRING && !strcmp(result_key, "Result") && !strcmp(result_value, "Success")) {
601 ret = IPHONE_E_SUCCESS;
603 } 602 }
604 603
605 /* store public key in config if pairing succeeded */ 604 /* store public key in config if pairing succeeded */
606 if (success) { 605 if (ret == IPHONE_E_SUCCESS) {
607 log_debug_msg("lockdownd_pair_device: pair success\n"); 606 log_debug_msg("lockdownd_pair_device: pair success\n");
608 store_device_public_key(uid, public_key_b64); 607 store_device_public_key(uid, public_key);
609 ret = IPHONE_E_SUCCESS; 608 ret = IPHONE_E_SUCCESS;
610 } else { 609 } else {
611 log_debug_msg("lockdownd_pair_device: pair failure\n"); 610 log_debug_msg("lockdownd_pair_device: pair failure\n");
612 ret = IPHONE_E_PAIRING_FAILED; 611 ret = IPHONE_E_PAIRING_FAILED;
613 } 612 }
614 free(public_key_b64); 613 free(public_key.data);
615 return ret; 614 return ret;
616} 615}
617 616
@@ -624,55 +623,59 @@ iphone_error_t lockdownd_pair_device(iphone_lckd_client_t control, char *uid, ch
624void lockdownd_close(iphone_lckd_client_t control) 623void lockdownd_close(iphone_lckd_client_t control)
625{ 624{
626 if (!control) 625 if (!control)
627 return; // IPHONE_E_INVALID_ARG; 626 return; //IPHONE_E_INVALID_ARG;
628 xmlDocPtr plist = new_plist(); 627
629 xmlNode *dict, *key;
630 char **dictionary;
631 int bytes = 0, i = 0; 628 int bytes = 0, i = 0;
632 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; 629 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
633 630
631 plist_t dict = plist_new_dict();
632 plist_add_sub_element(dict, PLIST_KEY, (void *) "Request", strlen("Request"));
633 plist_add_sub_element(dict, PLIST_STRING, (void *) "Goodbye", strlen("Goodbye"));
634
634 log_debug_msg("lockdownd_close() called\n"); 635 log_debug_msg("lockdownd_close() called\n");
635 dict = add_child_to_plist(plist, "dict", "\n", NULL, 0); 636 char *XML_content = NULL;
636 key = add_key_str_dict_element(plist, dict, "Request", "Goodbye", 1); 637 uint32_t length = 0;
637 char *XML_content;
638 uint32 length;
639 638
640 xmlDocDumpMemory(plist, (xmlChar **) & XML_content, &length); 639 plist_to_xml(dict, &XML_content, &length);
640 log_debug_msg("Send msg :\nsize : %i\nxml : %s", length, XML_content);
641 ret = iphone_lckd_send(control, XML_content, length, &bytes); 641 ret = iphone_lckd_send(control, XML_content, length, &bytes);
642 642
643 xmlFree(XML_content); 643 free(XML_content);
644 xmlFreeDoc(plist); 644 XML_content = NULL;
645 plist = NULL; 645 plist_free(dict);
646 dict = NULL;
647
646 ret = iphone_lckd_recv(control, &XML_content, &bytes); 648 ret = iphone_lckd_recv(control, &XML_content, &bytes);
649 log_debug_msg("Receive msg :\nsize : %i\nxml : %s", bytes, XML_content);
650 plist_from_xml(XML_content, bytes, &dict);
647 651
648 plist = xmlReadMemory(XML_content, bytes, NULL, NULL, 0);
649 if (!plist) {
650 fprintf(stderr, "lockdownd_close(): IPHONE_E_PLIST_ERROR\n");
651 return; //IPHONE_E_PLIST_ERROR;
652 }
653 dict = xmlDocGetRootElement(plist);
654 for (dict = dict->children; dict; dict = dict->next) {
655 if (!xmlStrcmp(dict->name, "dict"))
656 break;
657 }
658 if (!dict) { 652 if (!dict) {
659 fprintf(stderr, "lockdownd_close(): IPHONE_E_DICT_ERROR\n"); 653 log_debug_msg("lockdownd_close(): IPHONE_E_PLIST_ERROR\n");
660 return; //IPHONE_E_DICT_ERROR; 654 return; // IPHONE_E_PLIST_ERROR;
661 } 655 }
662 dictionary = read_dict_element_strings(dict);
663 xmlFreeDoc(plist);
664 free(XML_content);
665 656
666 for (i = 0; dictionary[i]; i += 2) { 657 plist_t query_node = plist_find_node(dict, PLIST_STRING, "Goodbye", strlen("Goodbye"));
667 if (!strcmp(dictionary[i], "Result") && !strcmp(dictionary[i + 1], "Success")) { 658 plist_t result_node = plist_get_next_sibling(query_node);
668 log_debug_msg("lockdownd_close(): success\n"); 659 plist_t value_node = plist_get_next_sibling(result_node);
669 ret = IPHONE_E_SUCCESS; 660
670 break; 661 plist_type result_type;
671 } 662 plist_type value_type;
663
664 char *result_value = NULL;
665 char *value_value = NULL;
666 uint64_t result_length = 0;
667 uint64_t value_length = 0;
668
669 plist_get_type_and_value(result_node, &result_type, (void *) (&result_value), &result_length);
670 plist_get_type_and_value(value_node, &value_type, (void *) (&value_value), &value_length);
671
672 if (result_type == PLIST_KEY &&
673 value_type == PLIST_STRING && !strcmp(result_value, "Result") && !strcmp(value_value, "Success")) {
674 log_debug_msg("lockdownd_close(): success\n");
675 ret = IPHONE_E_SUCCESS;
672 } 676 }
673 677
674 free_dictionary(dictionary); 678 return; // ret;
675 return; //ret;
676} 679}
677 680
678/** Generates the device certificate from the public key as well as the host 681/** Generates the device certificate from the public key as well as the host
@@ -680,25 +683,19 @@ void lockdownd_close(iphone_lckd_client_t control)
680 * 683 *
681 * @return IPHONE_E_SUCCESS on success. 684 * @return IPHONE_E_SUCCESS on success.
682 */ 685 */
683iphone_error_t lockdownd_gen_pair_cert(char *public_key_b64, char **device_cert_b64, char **host_cert_b64, 686iphone_error_t lockdownd_gen_pair_cert(gnutls_datum_t public_key, gnutls_datum_t * odevice_cert,
684 char **root_cert_b64) 687 gnutls_datum_t * ohost_cert, gnutls_datum_t * oroot_cert)
685{ 688{
686 if (!public_key_b64 || !device_cert_b64 || !host_cert_b64 || !root_cert_b64) 689 if (!public_key.data || !odevice_cert || !ohost_cert || !oroot_cert)
687 return IPHONE_E_INVALID_ARG; 690 return IPHONE_E_INVALID_ARG;
688 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; 691 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
689 692
690 gnutls_datum_t modulus = { NULL, 0 }; 693 gnutls_datum_t modulus = { NULL, 0 };
691 gnutls_datum_t exponent = { NULL, 0 }; 694 gnutls_datum_t exponent = { NULL, 0 };
692 695
693 /* first decode base64 public_key */
694 gnutls_datum_t pem_pub_key;
695 gsize decoded_size;
696 pem_pub_key.data = g_base64_decode(public_key_b64, &decoded_size);
697 pem_pub_key.size = decoded_size;
698
699 /* now decode the PEM encoded key */ 696 /* now decode the PEM encoded key */
700 gnutls_datum_t der_pub_key; 697 gnutls_datum_t der_pub_key;
701 if (GNUTLS_E_SUCCESS == gnutls_pem_base64_decode_alloc("RSA PUBLIC KEY", &pem_pub_key, &der_pub_key)) { 698 if (GNUTLS_E_SUCCESS == gnutls_pem_base64_decode_alloc("RSA PUBLIC KEY", &public_key, &der_pub_key)) {
702 699
703 /* initalize asn.1 parser */ 700 /* initalize asn.1 parser */
704 ASN1_TYPE pkcs1 = ASN1_TYPE_EMPTY; 701 ASN1_TYPE pkcs1 = ASN1_TYPE_EMPTY;
@@ -782,10 +779,18 @@ iphone_error_t lockdownd_gen_pair_cert(char *public_key_b64, char **device_cert_
782 dev_pem.data = gnutls_malloc(dev_pem.size); 779 dev_pem.data = gnutls_malloc(dev_pem.size);
783 gnutls_x509_crt_export(dev_cert, GNUTLS_X509_FMT_PEM, dev_pem.data, &dev_pem.size); 780 gnutls_x509_crt_export(dev_cert, GNUTLS_X509_FMT_PEM, dev_pem.data, &dev_pem.size);
784 781
785 /* now encode certificates for output */ 782 /* copy buffer for output */
786 *device_cert_b64 = g_base64_encode(dev_pem.data, dev_pem.size); 783 odevice_cert->data = malloc(dev_pem.size);
787 *host_cert_b64 = g_base64_encode(pem_host_cert.data, pem_host_cert.size); 784 memcpy(odevice_cert->data, dev_pem.data, dev_pem.size);
788 *root_cert_b64 = g_base64_encode(pem_root_cert.data, pem_root_cert.size); 785 odevice_cert->size = dev_pem.size;
786
787 ohost_cert->data = malloc(pem_host_cert.size);
788 memcpy(ohost_cert->data, pem_host_cert.data, pem_host_cert.size);
789 ohost_cert->size = pem_host_cert.size;
790
791 oroot_cert->data = malloc(pem_root_cert.size);
792 memcpy(oroot_cert->data, pem_root_cert.data, pem_root_cert.size);
793 oroot_cert->size = pem_root_cert.size;
789 } 794 }
790 gnutls_free(pem_root_priv.data); 795 gnutls_free(pem_root_priv.data);
791 gnutls_free(pem_root_cert.data); 796 gnutls_free(pem_root_cert.data);
@@ -797,7 +802,6 @@ iphone_error_t lockdownd_gen_pair_cert(char *public_key_b64, char **device_cert_
797 gnutls_free(exponent.data); 802 gnutls_free(exponent.data);
798 803
799 gnutls_free(der_pub_key.data); 804 gnutls_free(der_pub_key.data);
800 g_free(pem_pub_key.data);
801 805
802 return ret; 806 return ret;
803} 807}
@@ -811,124 +815,135 @@ iphone_error_t lockdownd_gen_pair_cert(char *public_key_b64, char **device_cert_
811 */ 815 */
812iphone_error_t lockdownd_start_SSL_session(iphone_lckd_client_t control, const char *HostID) 816iphone_error_t lockdownd_start_SSL_session(iphone_lckd_client_t control, const char *HostID)
813{ 817{
814 xmlDocPtr plist = new_plist(); 818 plist_t dict = NULL;
815 xmlNode *dict = add_child_to_plist(plist, "dict", "\n", NULL, 0); 819 char *XML_content = NULL;
816 xmlNode *key; 820 uint32_t length = 0, bytes = 0, return_me = 0;
817 char *what2send = NULL, **dictionary = NULL;
818 uint32 len = 0, bytes = 0, return_me = 0, i = 0;
819 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
820 // end variables
821 821
822 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
822 control->session_id[0] = '\0'; 823 control->session_id[0] = '\0';
823 824
824 key = add_key_str_dict_element(plist, dict, "HostID", HostID, 1); 825 /* Setup DevicePublicKey request plist */
825 if (!key) { 826 dict = plist_new_dict();
826 log_debug_msg("Couldn't add a key.\n"); 827 plist_add_sub_element(dict, PLIST_KEY, (void *) "HostID", strlen("HostID"));
827 xmlFreeDoc(plist); 828 plist_add_sub_element(dict, PLIST_STRING, (void *) HostID, strlen(HostID));
828 return IPHONE_E_DICT_ERROR; 829 plist_add_sub_element(dict, PLIST_KEY, (void *) "Request", strlen("Request"));
829 } 830 plist_add_sub_element(dict, PLIST_STRING, (void *) "StartSession", strlen("StartSession"));
830 key = add_key_str_dict_element(plist, dict, "Request", "StartSession", 1); 831 plist_to_xml(dict, &XML_content, &length);
831 if (!key) { 832 log_debug_msg("Send msg :\nsize : %i\nxml : %s", length, XML_content);
832 log_debug_msg("Couldn't add a key.\n");
833 xmlFreeDoc(plist);
834 return IPHONE_E_DICT_ERROR;
835 }
836 833
837 xmlDocDumpMemory(plist, (xmlChar **) & what2send, &len); 834 ret = iphone_lckd_send(control, XML_content, length, &bytes);
838 ret = iphone_lckd_send(control, what2send, len, &bytes);
839 835
840 xmlFree(what2send); 836 free(XML_content);
841 xmlFreeDoc(plist); 837 XML_content = NULL;
838 plist_free(dict);
839 dict = NULL;
842 840
843 if (ret != IPHONE_E_SUCCESS) 841 if (ret != IPHONE_E_SUCCESS)
844 return ret; 842 return ret;
845 843
846 if (bytes > 0) { 844 if (bytes > 0) {
847 ret = iphone_lckd_recv(control, &what2send, &len); 845 ret = iphone_lckd_recv(control, &XML_content, &bytes);
848 plist = xmlReadMemory(what2send, len, NULL, NULL, 0); 846 log_debug_msg("Receive msg :\nsize : %i\nxml : %s", bytes, XML_content);
849 dict = xmlDocGetRootElement(plist); 847 plist_from_xml(XML_content, bytes, &dict);
850 if (!dict) 848 if (!dict)
851 return IPHONE_E_DICT_ERROR; 849 return IPHONE_E_PLIST_ERROR;
852 for (dict = dict->children; dict; dict = dict->next) { 850
853 if (!xmlStrcmp(dict->name, "dict")) 851 plist_t query_node = plist_find_node(dict, PLIST_STRING, "StartSession", strlen("StartSession"));
854 break; 852 plist_t result_key_node = plist_get_next_sibling(query_node);
855 } 853 plist_t result_value_node = plist_get_next_sibling(result_key_node);
856 dictionary = read_dict_element_strings(dict); 854
857 xmlFreeDoc(plist); 855 plist_type result_key_type;
858 free(what2send); 856 plist_type result_value_type;
857 char *result_key = NULL;
858 char *result_value = NULL;
859 uint64_t key_length = 0;
860 uint64_t val_length = 0;
861
862 plist_get_type_and_value(result_key_node, &result_key_type, (void *) (&result_key), &key_length);
863 plist_get_type_and_value(result_value_node, &result_value_type, (void *) (&result_value), &val_length);
864
865 free(XML_content);
866 XML_content = NULL;
867 plist_free(dict);
868 dict = NULL;
859 ret = IPHONE_E_SSL_ERROR; 869 ret = IPHONE_E_SSL_ERROR;
860 for (i = 0; dictionary[i]; i += 2) { 870 if (result_key_type == PLIST_KEY &&
861 if (!strcmp(dictionary[i], "Result") && !strcmp(dictionary[i + 1], "Success")) { 871 result_value_type == PLIST_STRING && !strcmp(result_key, "Result") && !strcmp(result_value, "Success")) {
862 // Set up GnuTLS... 872 // Set up GnuTLS...
863 //gnutls_anon_client_credentials_t anoncred; 873 //gnutls_anon_client_credentials_t anoncred;
864 gnutls_certificate_credentials_t xcred; 874 gnutls_certificate_credentials_t xcred;
865 875
866 log_debug_msg("We started the session OK, now trying GnuTLS\n"); 876 log_debug_msg("We started the session OK, now trying GnuTLS\n");
867 errno = 0; 877 errno = 0;
868 gnutls_global_init(); 878 gnutls_global_init();
869 //gnutls_anon_allocate_client_credentials(&anoncred); 879 //gnutls_anon_allocate_client_credentials(&anoncred);
870 gnutls_certificate_allocate_credentials(&xcred); 880 gnutls_certificate_allocate_credentials(&xcred);
871 gnutls_certificate_set_x509_trust_file(xcred, "hostcert.pem", GNUTLS_X509_FMT_PEM); 881 gnutls_certificate_set_x509_trust_file(xcred, "hostcert.pem", GNUTLS_X509_FMT_PEM);
872 gnutls_init(control->ssl_session, GNUTLS_CLIENT); 882 gnutls_init(control->ssl_session, GNUTLS_CLIENT);
873 { 883 {
874 int protocol_priority[16] = { GNUTLS_SSL3, 0 }; 884 int protocol_priority[16] = { GNUTLS_SSL3, 0 };
875 int kx_priority[16] = { GNUTLS_KX_ANON_DH, GNUTLS_KX_RSA, 0 }; 885 int kx_priority[16] = { GNUTLS_KX_ANON_DH, GNUTLS_KX_RSA, 0 };
876 int cipher_priority[16] = { GNUTLS_CIPHER_AES_128_CBC, GNUTLS_CIPHER_AES_256_CBC, 0 }; 886 int cipher_priority[16] = { GNUTLS_CIPHER_AES_128_CBC, GNUTLS_CIPHER_AES_256_CBC, 0 };
877 int mac_priority[16] = { GNUTLS_MAC_SHA1, GNUTLS_MAC_MD5, 0 }; 887 int mac_priority[16] = { GNUTLS_MAC_SHA1, GNUTLS_MAC_MD5, 0 };
878 int comp_priority[16] = { GNUTLS_COMP_NULL, 0 }; 888 int comp_priority[16] = { GNUTLS_COMP_NULL, 0 };
879 889
880 gnutls_cipher_set_priority(*control->ssl_session, cipher_priority); 890 gnutls_cipher_set_priority(*control->ssl_session, cipher_priority);
881 gnutls_compression_set_priority(*control->ssl_session, comp_priority); 891 gnutls_compression_set_priority(*control->ssl_session, comp_priority);
882 gnutls_kx_set_priority(*control->ssl_session, kx_priority); 892 gnutls_kx_set_priority(*control->ssl_session, kx_priority);
883 gnutls_protocol_set_priority(*control->ssl_session, protocol_priority); 893 gnutls_protocol_set_priority(*control->ssl_session, protocol_priority);
884 gnutls_mac_set_priority(*control->ssl_session, mac_priority); 894 gnutls_mac_set_priority(*control->ssl_session, mac_priority);
885 895
886 } 896 }
887 gnutls_credentials_set(*control->ssl_session, GNUTLS_CRD_CERTIFICATE, xcred); // this part is killing me. 897 gnutls_credentials_set(*control->ssl_session, GNUTLS_CRD_CERTIFICATE, xcred); // this part is killing me.
888 898
889 log_debug_msg("GnuTLS step 1...\n"); 899 log_debug_msg("GnuTLS step 1...\n");
890 gnutls_transport_set_ptr(*control->ssl_session, (gnutls_transport_ptr_t) control); 900 gnutls_transport_set_ptr(*control->ssl_session, (gnutls_transport_ptr_t) control);
891 log_debug_msg("GnuTLS step 2...\n"); 901 log_debug_msg("GnuTLS step 2...\n");
892 gnutls_transport_set_push_function(*control->ssl_session, (gnutls_push_func) & lockdownd_secuwrite); 902 gnutls_transport_set_push_function(*control->ssl_session, (gnutls_push_func) & lockdownd_secuwrite);
893 log_debug_msg("GnuTLS step 3...\n"); 903 log_debug_msg("GnuTLS step 3...\n");
894 gnutls_transport_set_pull_function(*control->ssl_session, (gnutls_pull_func) & lockdownd_securead); 904 gnutls_transport_set_pull_function(*control->ssl_session, (gnutls_pull_func) & lockdownd_securead);
895 log_debug_msg("GnuTLS step 4 -- now handshaking...\n"); 905 log_debug_msg("GnuTLS step 4 -- now handshaking...\n");
896 906
897 if (errno) 907 if (errno)
898 log_debug_msg("WARN: errno says %s before handshake!\n", strerror(errno)); 908 log_debug_msg("WARN: errno says %s before handshake!\n", strerror(errno));
899 return_me = gnutls_handshake(*control->ssl_session); 909 return_me = gnutls_handshake(*control->ssl_session);
900 log_debug_msg("GnuTLS handshake done...\n"); 910 log_debug_msg("GnuTLS handshake done...\n");
901 911
902 if (return_me != GNUTLS_E_SUCCESS) { 912 if (return_me != GNUTLS_E_SUCCESS) {
903 log_debug_msg("GnuTLS reported something wrong.\n"); 913 log_debug_msg("GnuTLS reported something wrong.\n");
904 gnutls_perror(return_me); 914 gnutls_perror(return_me);
905 log_debug_msg("oh.. errno says %s\n", strerror(errno)); 915 log_debug_msg("oh.. errno says %s\n", strerror(errno));
906 return IPHONE_E_SSL_ERROR; 916 return IPHONE_E_SSL_ERROR;
907 } else { 917 } else {
908 control->in_SSL = 1; 918 control->in_SSL = 1;
909 ret = IPHONE_E_SUCCESS; 919 ret = IPHONE_E_SUCCESS;
910 } 920 }
911 } else if (!strcmp(dictionary[i], "SessionID")) { 921 }
922 //store session id
923 plist_t session_node = plist_find_node(dict, PLIST_KEY, "SessionID", strlen("SessionID"));
924 if (session_node) {
925
926 plist_type session_node_val_type;
927 char *session_id = NULL;
928 uint64_t session_id_length = 0;
929 plist_t session_node_val = plist_get_next_sibling(session_node);
930
931 plist_get_type_and_value(session_node_val, &session_node_val_type, (void *) (&session_id),
932 &session_id_length);
933 if (session_node_val_type == PLIST_STRING && session_id_length > 0) {
912 // we need to store the session ID for StopSession 934 // we need to store the session ID for StopSession
913 strcpy(control->session_id, dictionary[i + 1]); 935 strcpy(control->session_id, session_id);
914 log_debug_msg("SessionID: %s\n", control->session_id); 936 log_debug_msg("SessionID: %s\n", control->session_id);
915 free_dictionary(dictionary);
916 return ret; 937 return ret;
917 } 938 }
918 } 939 }
940
919 if (ret == IPHONE_E_SUCCESS) { 941 if (ret == IPHONE_E_SUCCESS) {
920 log_debug_msg("Failed to get SessionID!\n"); 942 log_debug_msg("Failed to get SessionID!\n");
921 return ret; 943 return ret;
922 } 944 }
923 945
924 log_debug_msg("Apparently failed negotiating with lockdownd.\n"); 946 log_debug_msg("Apparently failed negotiating with lockdownd.\n");
925 log_debug_msg("Responding dictionary: \n");
926 for (i = 0; dictionary[i]; i += 2) {
927 log_debug_msg("\t%s: %s\n", dictionary[i], dictionary[i + 1]);
928 }
929
930
931 free_dictionary(dictionary);
932 return IPHONE_E_SSL_ERROR; 947 return IPHONE_E_SSL_ERROR;
933 } else { 948 } else {
934 log_debug_msg("Didn't get enough bytes.\n"); 949 log_debug_msg("Didn't get enough bytes.\n");
@@ -1060,81 +1075,90 @@ iphone_error_t iphone_lckd_start_service(iphone_lckd_client_t client, const char
1060 if (!client->in_SSL && !lockdownd_start_SSL_session(client, host_id)) 1075 if (!client->in_SSL && !lockdownd_start_SSL_session(client, host_id))
1061 return IPHONE_E_SSL_ERROR; 1076 return IPHONE_E_SSL_ERROR;
1062 1077
1063 char *XML_query, **dictionary; 1078
1064 uint32 length, i = 0, port_loc = 0, bytes = 0; 1079 plist_t dict = NULL;
1065 uint8 result = 0; 1080 char *XML_content = NULL;
1081 uint32_t length, i = 0, port_loc = 0, bytes = 0;
1066 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; 1082 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
1067 1083
1068 free(host_id); 1084 free(host_id);
1069 host_id = NULL; 1085 host_id = NULL;
1070 1086
1071 xmlDocPtr plist = new_plist(); 1087 dict = plist_new_dict();
1072 xmlNode *dict = add_child_to_plist(plist, "dict", "\n", NULL, 0); 1088 plist_add_sub_element(dict, PLIST_KEY, (void *) "Request", strlen("Request"));
1073 xmlNode *key; 1089 plist_add_sub_element(dict, PLIST_STRING, (void *) "StartService", strlen("StartService"));
1074 key = add_key_str_dict_element(plist, dict, "Request", "StartService", 1); 1090 plist_add_sub_element(dict, PLIST_KEY, (void *) "Service", strlen("Service"));
1075 if (!key) { 1091 plist_add_sub_element(dict, PLIST_STRING, (void *) service, strlen(service));
1076 xmlFreeDoc(plist); 1092 plist_to_xml(dict, &XML_content, &length);
1077 return IPHONE_E_UNKNOWN_ERROR; 1093
1078 } 1094 /* send to iPhone */
1079 key = add_key_str_dict_element(plist, dict, "Service", service, 1); 1095 log_debug_msg("Send msg :\nsize : %i\nxml : %s", length, XML_content);
1080 if (!key) { 1096 ret = iphone_lckd_send(client, XML_content, length, &bytes);
1081 xmlFreeDoc(plist);
1082 return IPHONE_E_UNKNOWN_ERROR;
1083 }
1084 1097
1085 xmlDocDumpMemory(plist, (xmlChar **) & XML_query, &length); 1098 free(XML_content);
1099 XML_content = NULL;
1100 plist_free(dict);
1101 dict = NULL;
1086 1102
1087 ret = iphone_lckd_send(client, XML_query, length, &bytes);
1088 free(XML_query);
1089 if (IPHONE_E_SUCCESS != ret) 1103 if (IPHONE_E_SUCCESS != ret)
1090 return ret; 1104 return ret;
1091 1105
1092 ret = iphone_lckd_recv(client, &XML_query, &bytes); 1106 ret = iphone_lckd_recv(client, &XML_content, &bytes);
1093 xmlFreeDoc(plist); 1107
1094 if (IPHONE_E_SUCCESS != ret) 1108 if (IPHONE_E_SUCCESS != ret)
1095 return ret; 1109 return ret;
1096 1110
1111 plist_from_xml(XML_content, bytes, &dict);
1112 if (!dict)
1113 return IPHONE_E_PLIST_ERROR;
1114
1115
1097 if (bytes <= 0) 1116 if (bytes <= 0)
1098 return IPHONE_E_NOT_ENOUGH_DATA; 1117 return IPHONE_E_NOT_ENOUGH_DATA;
1099 else { 1118 else {
1100 plist = xmlReadMemory(XML_query, bytes, NULL, NULL, 0);
1101 if (!plist)
1102 return IPHONE_E_UNKNOWN_ERROR;
1103 dict = xmlDocGetRootElement(plist);
1104 if (!dict)
1105 return IPHONE_E_UNKNOWN_ERROR;
1106 for (dict = dict->children; dict; dict = dict->next) {
1107 if (!xmlStrcmp(dict->name, "dict"))
1108 break;
1109 }
1110 1119
1111 if (!dict) 1120 plist_t query_node = plist_find_node(dict, PLIST_STRING, "StartService", strlen("StartService"));
1112 return IPHONE_E_UNKNOWN_ERROR; 1121 plist_t result_key_node = plist_get_next_sibling(query_node);
1113 dictionary = read_dict_element_strings(dict); 1122 plist_t result_value_node = plist_get_next_sibling(result_key_node);
1114 1123
1115 for (i = 0; dictionary[i]; i += 2) { 1124 plist_t port_key_node = plist_find_node(dict, PLIST_KEY, "Port", strlen("Port"));
1116 log_debug_msg("lockdownd_start_service() dictionary %s: %s\n", dictionary[i], dictionary[i + 1]); 1125 plist_t port_value_node = plist_get_next_sibling(port_key_node);
1117 1126
1118 if (!xmlStrcmp(dictionary[i], "Port")) { 1127 plist_type result_key_type;
1119 port_loc = atoi(dictionary[i + 1]); 1128 plist_type result_value_type;
1120 log_debug_msg("lockdownd_start_service() atoi'd port: %i\n", port); 1129 plist_type port_key_type;
1121 } 1130 plist_type port_value_type;
1122 1131 char *result_key = NULL;
1123 if (!xmlStrcmp(dictionary[i], "Result")) { 1132 char *result_value = NULL;
1124 if (!xmlStrcmp(dictionary[i + 1], "Success")) { 1133 char *port_key = NULL;
1125 result = 1; 1134 uint64_t res_key_length = 0;
1126 } 1135 uint64_t res_val_length = 0;
1127 } 1136 uint64_t port_key_length = 0;
1137 uint64_t port_val_length = 0;
1138 uint64_t port_value = 0;
1139
1140 plist_get_type_and_value(result_key_node, &result_key_type, (void *) (&result_key), &res_key_length);
1141 plist_get_type_and_value(result_value_node, &result_value_type, (void *) (&result_value), &res_val_length);
1142 plist_get_type_and_value(port_key_node, &port_key_type, (void *) (&port_key), &port_key_length);
1143 plist_get_type_and_value(port_value_node, &port_value_type, (void *) (&port_value), &port_val_length);
1144
1145 if (result_key_type == PLIST_KEY &&
1146 result_value_type == PLIST_STRING &&
1147 port_key_type == PLIST_KEY &&
1148 port_value_type == PLIST_UINT &&
1149 !strcmp(result_key, "Result") && !strcmp(result_value, "Success") && !strcmp(port_key, "Port")) {
1150 port_loc = port_value;
1151 ret = IPHONE_E_SUCCESS;
1128 } 1152 }
1129 1153
1130 log_debug_msg("lockdownd_start_service(): DATA RECEIVED:\n\n"); 1154 log_debug_msg("lockdownd_start_service(): DATA RECEIVED:\n\n");
1131 log_debug_msg(XML_query); 1155 log_debug_msg(XML_content);
1132 log_debug_msg("end data received by lockdownd_start_service()\n"); 1156 log_debug_msg("end data received by lockdownd_start_service()\n");
1133 1157
1134 free(XML_query); 1158 free(XML_content);
1135 xmlFreeDoc(plist); 1159 plist_free(dict);
1136 free_dictionary(dictionary); 1160 dict = NULL;
1137 if (port && result) { 1161 if (port && ret == IPHONE_E_SUCCESS) {
1138 *port = port_loc; 1162 *port = port_loc;
1139 return IPHONE_E_SUCCESS; 1163 return IPHONE_E_SUCCESS;
1140 } else 1164 } else
diff --git a/src/lockdown.h b/src/lockdown.h
index 8b4f27c..cdc46b8 100644
--- a/src/lockdown.h
+++ b/src/lockdown.h
@@ -23,7 +23,6 @@
23#define LOCKDOWND_H 23#define LOCKDOWND_H
24 24
25#include "usbmux.h" 25#include "usbmux.h"
26#include "plist.h"
27 26
28#include <gnutls/gnutls.h> 27#include <gnutls/gnutls.h>
29#include <string.h> 28#include <string.h>
@@ -41,18 +40,16 @@ struct iphone_lckd_client_int {
41 char session_id[40]; 40 char session_id[40];
42}; 41};
43 42
44char *lockdownd_generate_hostid(void);
45
46iphone_lckd_client_t new_lockdownd_client(iphone_device_t phone); 43iphone_lckd_client_t new_lockdownd_client(iphone_device_t phone);
47iphone_error_t lockdownd_hello(iphone_lckd_client_t control); 44iphone_error_t lockdownd_hello(iphone_lckd_client_t control);
48iphone_error_t lockdownd_generic_get_value(iphone_lckd_client_t control, const char *req_key, const char *req_string, 45iphone_error_t lockdownd_generic_get_value(iphone_lckd_client_t control, const char *req_key, char *req_string,
49 char **value); 46 gnutls_datum_t * value);
50iphone_error_t lockdownd_get_device_uid(iphone_lckd_client_t control, char **uid); 47iphone_error_t lockdownd_get_device_uid(iphone_lckd_client_t control, char **uid);
51iphone_error_t lockdownd_get_device_public_key(iphone_lckd_client_t control, char **public_key); 48iphone_error_t lockdownd_get_device_public_key(iphone_lckd_client_t control, gnutls_datum_t * public_key);
52 49
53iphone_error_t lockdownd_gen_pair_cert(char *public_key_b64, char **device_cert_b64, char **host_cert_b64, 50iphone_error_t lockdownd_gen_pair_cert(gnutls_datum_t public_key, gnutls_datum_t * device_cert,
54 char **root_cert_b64); 51 gnutls_datum_t * host_cert, gnutls_datum_t * root_cert);
55iphone_error_t lockdownd_pair_device(iphone_lckd_client_t control, char *public_key, char *host_id); 52iphone_error_t lockdownd_pair_device(iphone_lckd_client_t control, char *uid, char *host_id);
56void lockdownd_close(iphone_lckd_client_t control); 53void lockdownd_close(iphone_lckd_client_t control);
57 54
58// SSL functions 55// 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 @@
1/*
2 * plist.c
3 * Builds plist XML structures.
4 *
5 * Copyright (c) 2008 Zach C. All Rights Reserved.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#include <libxml/parser.h>
23#include <libxml/tree.h>
24#include <string.h>
25#include <assert.h>
26#include "plist.h"
27
28const char *plist_base = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
29<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n\
30<plist version=\"1.0\">\n\
31</plist>\0";
32
33/** Formats a block of text to be a given indentation and width.
34 *
35 * The total width of the return string will be depth + cols.
36 *
37 * @param buf The string to format.
38 * @param cols The number of text columns for returned block of text.
39 * @param depth The number of tabs to indent the returned block of text.
40 *
41 * @return The formatted string.
42 */
43static char *format_string(const char *buf, int cols, int depth)
44{
45 int colw = depth + cols + 1;
46 int len = strlen(buf);
47 int nlines = len / cols + 1;
48 char *new_buf = (char *) malloc(nlines * colw + depth + 1);
49 int i = 0;
50 int j = 0;
51
52 assert(cols >= 0);
53 assert(depth >= 0);
54
55 // Inserts new lines and tabs at appropriate locations
56 for (i = 0; i < nlines; i++) {
57 new_buf[i * colw] = '\n';
58 for (j = 0; j < depth; j++)
59 new_buf[i * colw + 1 + j] = '\t';
60 memcpy(new_buf + i * colw + 1 + depth, buf + i * cols, cols);
61 }
62 new_buf[len + (1 + depth) * nlines] = '\n';
63
64 // Inserts final row of indentation and termination character
65 for (j = 0; j < depth; j++)
66 new_buf[len + (1 + depth) * nlines + 1 + j] = '\t';
67 new_buf[len + (1 + depth) * nlines + depth + 1] = '\0';
68
69 return new_buf;
70}
71
72/** Creates a new plist XML document.
73 *
74 * @return The plist XML document.
75 */
76xmlDocPtr new_plist(void)
77{
78 char *plist = strdup(plist_base);
79 xmlDocPtr plist_xml = xmlReadMemory(plist, strlen(plist), NULL, NULL, 0);
80
81 if (!plist_xml)
82 return NULL;
83
84 free(plist);
85
86 return plist_xml;
87}
88
89/** Destroys a previously created XML document.
90 *
91 * @param plist The XML document to destroy.
92 */
93void free_plist(xmlDocPtr plist)
94{
95 if (!plist)
96 return;
97
98 xmlFreeDoc(plist);
99}
100
101/** Adds a new node as a child to a given node.
102 *
103 * This is a lower level function so you probably want to use
104 * add_key_str_dict_element, add_key_dict_node or add_key_data_dict_element
105 * instead.
106 *
107 * @param plist The plist XML document to which the to_node belongs.
108 * @param name The name of the new node.
109 * @param content The string containing the text node of the new node.
110 * @param to_node The node to attach the child node to. If none is given, the
111 * root node of the given document is used.
112 * @param depth The number of tabs to indent the new node.
113 *
114 * @return The newly created node.
115 */
116xmlNode *add_child_to_plist(xmlDocPtr plist, const char *name, const char *content, xmlNode * to_node, int depth)
117{
118 int i = 0;
119 xmlNode *child;
120
121 if (!plist)
122 return NULL;
123 assert(depth >= 0);
124 if (!to_node)
125 to_node = xmlDocGetRootElement(plist);
126
127 for (i = 0; i < depth; i++) {
128 xmlNodeAddContent(to_node, "\t");
129 }
130 child = xmlNewChild(to_node, NULL, name, content);
131 xmlNodeAddContent(to_node, "\n");
132
133 return child;
134}
135
136/** Adds a string key-pair to a plist XML document.
137 *
138 * @param plist The plist XML document to add the new node to.
139 * @param dict The dictionary node within the plist XML document to add the new node to.
140 * @param key The string containing the key value.
141 * @param value The string containing the value.
142 * @param depth The number of tabs to indent the new node.
143 *
144 * @return The newly created key node.
145 */
146xmlNode *add_key_str_dict_element(xmlDocPtr plist, xmlNode * dict, const char *key, const char *value, int depth)
147{
148 xmlNode *keyPtr;
149
150 keyPtr = add_child_to_plist(plist, "key", key, dict, depth);
151 add_child_to_plist(plist, "string", value, dict, depth);
152
153 return keyPtr;
154}
155
156/** Adds a new dictionary key-pair to a plist XML document.
157 *
158 * @param plist The plist XML document to add the new node to.
159 * @param dict The dictionary node within the plist XML document to add the new node to.
160 * @param key The string containing the key value.
161 * @param value The string containing the value.
162 * @param depth The number of tabs to indent the new node.
163 *
164 * @return The newly created dict node.
165 */
166xmlNode *add_key_dict_node(xmlDocPtr plist, xmlNode * dict, const char *key, const char *value, int depth)
167{
168 xmlNode *child;
169
170 add_child_to_plist(plist, "key", key, dict, depth);
171 child = add_child_to_plist(plist, "dict", value, dict, depth);
172
173 return child;
174}
175
176/** Adds a new data dictionary key-pair to a plist XML document.
177 *
178 * @param plist The plist XML document to add the new node to.
179 * @param dict The dictionary node within the plist XML document to add the new node to.
180 * @param key The string containing the key value.
181 * @param value The string containing the value.
182 * @param depth The number of tabs to indent the new node.
183 *
184 * @return The newly created key node.
185 */
186xmlNode *add_key_data_dict_element(xmlDocPtr plist, xmlNode * dict, const char *key, const char *value, int depth)
187{
188 xmlNode *keyPtr;
189
190 keyPtr = add_child_to_plist(plist, "key", key, dict, depth);
191 add_child_to_plist(plist, "data", format_string(value, 60, depth), dict, depth);
192
193 return keyPtr;
194}
195
196/** Reads a set of keys and strings into an array from a plist XML document.
197 *
198 * @param dict The root XMLNode of a plist XML document to be read.
199 *
200 * @return An array where each even number is a key and the odd numbers are
201 * values. If the odd number is \0, that's the end of the list.
202 */
203char **read_dict_element_strings(xmlNode * dict)
204{
205 char **return_me = NULL, **old = NULL;
206 int current_length = 0;
207 int current_pos = 0;
208 xmlNode *dict_walker;
209
210 for (dict_walker = dict->children; dict_walker; dict_walker = dict_walker->next) {
211 if (!xmlStrcmp(dict_walker->name, "key")) {
212 current_length += 2;
213 old = return_me;
214 return_me = realloc(return_me, sizeof(char *) * current_length);
215 if (!return_me) {
216 free(old);
217 return NULL;
218 }
219 return_me[current_pos++] = xmlNodeGetContent(dict_walker);
220 return_me[current_pos++] = xmlNodeGetContent(dict_walker->next->next);
221 }
222 }
223
224 old = return_me;
225 return_me = realloc(return_me, sizeof(char *) * (current_length + 1));
226 return_me[current_pos] = NULL;
227
228 return return_me;
229}
230
231/** Destroys a dictionary as returned by read_dict_element_strings
232 */
233void free_dictionary(char **dictionary)
234{
235 int i = 0;
236
237 if (!dictionary)
238 return;
239
240 for (i = 0; dictionary[i]; i++) {
241 free(dictionary[i]);
242 }
243
244 free(dictionary);
245}
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 @@
1/*
2 * plist.h
3 * contains structures and the like for plists
4 *
5 * Copyright (c) 2008 Zach C. All Rights Reserved.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#ifndef PLIST_H
23#define PLIST_H
24
25#include <libxml/parser.h>
26#include <libxml/tree.h>
27
28xmlNode *add_key_dict_node(xmlDocPtr plist, xmlNode * dict, const char *key, const char *value, int depth);
29xmlNode *add_key_str_dict_element(xmlDocPtr plist, xmlNode * dict, const char *key, const char *value, int depth);
30xmlNode *add_key_data_dict_element(xmlDocPtr plist, xmlNode * dict, const char *key, const char *value, int depth);
31xmlNode *add_child_to_plist(xmlDocPtr plist, const char *name, const char *content, xmlNode * to_node, int depth);
32
33void free_plist(xmlDocPtr plist);
34xmlDocPtr new_plist(void);
35
36char **read_dict_element_strings(xmlNode * dict);
37void free_dictionary(char **dictionary);
38#endif
diff --git a/src/usbmux.c b/src/usbmux.c
index c7ac7ef..eb7ec97 100644
--- a/src/usbmux.c
+++ b/src/usbmux.c
@@ -38,7 +38,7 @@ static int clients = 0;
38 * 38 *
39 * @return A USBMux packet 39 * @return A USBMux packet
40 */ 40 */
41usbmux_tcp_header *new_mux_packet(uint16 s_port, uint16 d_port) 41usbmux_tcp_header *new_mux_packet(uint16_t s_port, uint16_t d_port)
42{ 42{
43 usbmux_tcp_header *conn = (usbmux_tcp_header *) malloc(sizeof(usbmux_tcp_header)); 43 usbmux_tcp_header *conn = (usbmux_tcp_header *) malloc(sizeof(usbmux_tcp_header));
44 conn->type = htonl(6); 44 conn->type = htonl(6);
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 @@
22#include <sys/types.h> 22#include <sys/types.h>
23#include <stdlib.h> 23#include <stdlib.h>
24#include <stdint.h> 24#include <stdint.h>
25#include "libiphone/libiphone.h"
25 26
26#ifndef USBMUX_H 27#ifndef USBMUX_H
27#define USBMUX_H 28#define USBMUX_H
@@ -30,17 +31,12 @@
30#include "iphone.h" 31#include "iphone.h"
31#endif 32#endif
32 33
33typedef uint16_t uint16;
34typedef uint32_t uint32;
35typedef uint8_t uint8;
36
37
38typedef struct { 34typedef struct {
39 uint32 type, length; 35 uint32_t type, length;
40 uint16 sport, dport; 36 uint16_t sport, dport;
41 uint32 scnt, ocnt; 37 uint32_t scnt, ocnt;
42 uint8 offset, tcp_flags; 38 uint8_t offset, tcp_flags;
43 uint16 window, nullnull, length16; 39 uint16_t window, nullnull, length16;
44} usbmux_tcp_header; 40} usbmux_tcp_header;
45 41
46struct iphone_umux_client_int { 42struct iphone_umux_client_int {
@@ -50,10 +46,10 @@ struct iphone_umux_client_int {
50 int r_len; 46 int r_len;
51}; 47};
52 48
53usbmux_tcp_header *new_mux_packet(uint16 s_port, uint16 d_port); 49usbmux_tcp_header *new_mux_packet(uint16_t s_port, uint16_t d_port);
54 50
55typedef struct { 51typedef struct {
56 uint32 type, length, major, minor, allnull; 52 uint32_t type, length, major, minor, allnull;
57} usbmux_version_header; 53} usbmux_version_header;
58 54
59usbmux_version_header *version_header(void); 55usbmux_version_header *version_header(void);
diff --git a/src/userpref.c b/src/userpref.c
index 5f227b0..3e5eb06 100644
--- a/src/userpref.c
+++ b/src/userpref.c
@@ -111,10 +111,10 @@ int is_device_known(char *uid)
111 * @return 1 on success and 0 if no public key is given or if it has already 111 * @return 1 on success and 0 if no public key is given or if it has already
112 * been marked as connected previously. 112 * been marked as connected previously.
113 */ 113 */
114int store_device_public_key(char *uid, char *public_key) 114int store_device_public_key(char *uid, gnutls_datum_t public_key)
115{ 115{
116 116
117 if (NULL == public_key || is_device_known(uid)) 117 if (NULL == public_key.data || is_device_known(uid))
118 return 0; 118 return 0;
119 119
120 /* ensure config directory exists */ 120 /* ensure config directory exists */
@@ -124,15 +124,11 @@ int store_device_public_key(char *uid, char *public_key)
124 gchar *device_file = g_strconcat(uid, ".pem", NULL); 124 gchar *device_file = g_strconcat(uid, ".pem", NULL);
125 gchar *pem = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIPHONE_CONF_DIR, device_file, NULL); 125 gchar *pem = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), LIBIPHONE_CONF_DIR, device_file, NULL);
126 126
127 /* decode public key for storing */
128 gsize decoded_size;
129 gchar *data = g_base64_decode(public_key, &decoded_size);
130 /* store file */ 127 /* store file */
131 FILE *pFile = fopen(pem, "wb"); 128 FILE *pFile = fopen(pem, "wb");
132 fwrite(data, 1, decoded_size, pFile); 129 fwrite(public_key.data, 1, public_key.size, pFile);
133 fclose(pFile); 130 fclose(pFile);
134 g_free(pem); 131 g_free(pem);
135 g_free(data);
136 g_free(device_file); 132 g_free(device_file);
137 return 1; 133 return 1;
138} 134}
diff --git a/src/userpref.h b/src/userpref.h
index e7835d0..7e606eb 100644
--- a/src/userpref.h
+++ b/src/userpref.h
@@ -40,7 +40,7 @@ int is_device_known(char *uid);
40/** 40/**
41 * @return 1 if everything went well. Returns 0 otherwise. 41 * @return 1 if everything went well. Returns 0 otherwise.
42 */ 42 */
43int store_device_public_key(char *uid, char *public_key); 43int store_device_public_key(char *uid, gnutls_datum_t public_key);
44 44
45/** 45/**
46 * @return 1 if everything went well. Returns 0 otherwise. 46 * @return 1 if everything went well. Returns 0 otherwise.