summaryrefslogtreecommitdiffstats
path: root/src/lockdown.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lockdown.c')
-rw-r--r--src/lockdown.c1007
1 files changed, 495 insertions, 512 deletions
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 @@
1/* 1/*
2 * lockdown.c 2 * lockdown.c
3 * libiphone built-in lockdownd client 3 * libiphone built-in lockdownd client
4 * 4 *
5 * Copyright (c) 2008 Zach C. All Rights Reserved. 5 * Copyright (c) 2008 Zach C. All Rights Reserved.
6 * 6 *
7 * This library is free software; you can redistribute it and/or 7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public 8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either 9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version. 10 * version 2.1 of the License, or (at your option) any later version.
11 * 11 *
12 * This library is distributed in the hope that it will be useful, 12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details. 15 * Lesser General Public License for more details.
16 * 16 *
17 * You should have received a copy of the GNU Lesser General Public 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 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 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */ 20 */
21 21
22#include "usbmux.h" 22#include "usbmux.h"
@@ -31,6 +31,9 @@
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
36
34const ASN1_ARRAY_TYPE pkcs1_asn1_tab[] = { 37const ASN1_ARRAY_TYPE pkcs1_asn1_tab[] = {
35 {"PKCS1", 536872976, 0}, 38 {"PKCS1", 536872976, 0},
36 {0, 1073741836, 0}, 39 {0, 1073741836, 0},
@@ -40,35 +43,6 @@ const ASN1_ARRAY_TYPE pkcs1_asn1_tab[] = {
40 {0, 0, 0} 43 {0, 0, 0}
41}; 44};
42 45
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. 46/** Creates a lockdownd client for the give iPhone.
73 * 47 *
74 * @param phone The iPhone to create a lockdownd client for 48 * @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)
93 67
94/** 68/**
95 * Closes the lockdownd communication session, by sending 69 * Closes the lockdownd communication session, by sending
96 * the StopSession Request to the device. 70 * the StopSession Request to the device.
97 * 71 *
98 * @param control The lockdown client 72 * @param control The lockdown client
99 */ 73 */
100static void iphone_lckd_stop_session(iphone_lckd_client_t control) 74static void iphone_lckd_stop_session(iphone_lckd_client_t control)
101{ 75{
102 if (!control) 76 if (!control)
103 return; // IPHONE_E_INVALID_ARG; 77 return; //IPHONE_E_INVALID_ARG;
104 xmlDocPtr plist = new_plist(); 78
105 xmlNode *dict, *key;
106 char **dictionary;
107 int bytes = 0, i = 0;
108 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; 79 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
109 80
110 log_debug_msg("lockdownd_stop_session() called\n"); 81 plist_t dict = plist_new_dict();
111 dict = add_child_to_plist(plist, "dict", "\n", NULL, 0); 82 plist_add_sub_key_el(dict, "Request");
112 key = add_key_str_dict_element(plist, dict, "Request", "StopSession", 1); 83 plist_add_sub_string_el(dict, "StopSession");
113 key = add_key_str_dict_element(plist, dict, "SessionID", control->session_id, 1); 84 plist_add_sub_key_el(dict, "SessionID");
85 plist_add_sub_string_el(dict, control->session_id);
114 86
115 char *XML_content; 87 log_dbg_msg(DBGMASK_LOCKDOWND, "iphone_lckd_stop_session() called\n");
116 uint32 length;
117 88
118 xmlDocDumpMemory(plist, (xmlChar **) & XML_content, &length); 89 ret = iphone_lckd_send(control, dict);
119 ret = iphone_lckd_send(control, XML_content, length, &bytes);
120 90
121 xmlFree(XML_content); 91 plist_free(dict);
122 xmlFreeDoc(plist); 92 dict = NULL;
123 plist = NULL; 93
124 ret = iphone_lckd_recv(control, &XML_content, &bytes); 94 ret = iphone_lckd_recv(control, &dict);
125 95
126 plist = xmlReadMemory(XML_content, bytes, NULL, NULL, 0);
127 if (!plist) {
128 log_debug_msg("lockdownd_stop_session(): IPHONE_E_PLIST_ERROR\n");
129 return; //IPHONE_E_PLIST_ERROR;
130 }
131 dict = xmlDocGetRootElement(plist);
132 for (dict = dict->children; dict; dict = dict->next) {
133 if (!xmlStrcmp(dict->name, "dict"))
134 break;
135 }
136 if (!dict) { 96 if (!dict) {
137 log_debug_msg("lockdownd_stop_session(): IPHONE_E_DICT_ERROR\n"); 97 log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_stop_session(): IPHONE_E_PLIST_ERROR\n");
138 return; //IPHONE_E_DICT_ERROR; 98 return; // IPHONE_E_PLIST_ERROR;
139 } 99 }
140 dictionary = read_dict_element_strings(dict);
141 xmlFreeDoc(plist);
142 free(XML_content);
143 100
144 for (i = 0; dictionary[i]; i += 2) { 101 plist_t query_node = plist_find_node_by_string(dict, "StopSession");
145 if (!strcmp(dictionary[i], "Result") && !strcmp(dictionary[i + 1], "Success")) { 102 plist_t result_node = plist_get_next_sibling(query_node);
146 log_debug_msg("lockdownd_stop_session(): success\n"); 103 plist_t value_node = plist_get_next_sibling(result_node);
104
105 plist_type result_type = plist_get_node_type(result_node);
106 plist_type value_type = plist_get_node_type(value_node);
107
108 if (result_type == PLIST_KEY && value_type == PLIST_STRING) {
109
110 char *result_value = NULL;
111 char *value_value = NULL;
112
113 plist_get_key_val(result_node, &result_value);
114 plist_get_string_val(value_node, &value_value);
115
116 if (!strcmp(result_value, "Result") && !strcmp(value_value, "Success")) {
117 log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_stop_session(): success\n");
147 ret = IPHONE_E_SUCCESS; 118 ret = IPHONE_E_SUCCESS;
148 break;
149 } 119 }
120 free(result_value);
121 free(value_value);
150 } 122 }
123 plist_free(dict);
124 dict = NULL;
151 125
152 free_dictionary(dictionary); 126 return; // ret;
153 return; //ret;
154} 127}
155 128
156/** 129/**
157 * Shuts down the SSL session by first calling iphone_lckd_stop_session 130 * Shuts down the SSL session by first calling iphone_lckd_stop_session
158 * to cleanly close the lockdownd communication session, and then 131 * to cleanly close the lockdownd communication session, and then
159 * performing a close notify, which is done by "gnutls_bye". 132 * performing a close notify, which is done by "gnutls_bye".
160 * 133 *
161 * @param client The lockdown client 134 * @param client The lockdown client
@@ -163,14 +136,14 @@ static void iphone_lckd_stop_session(iphone_lckd_client_t control)
163static void iphone_lckd_stop_SSL_session(iphone_lckd_client_t client) 136static void iphone_lckd_stop_SSL_session(iphone_lckd_client_t client)
164{ 137{
165 if (!client) { 138 if (!client) {
166 log_debug_msg("lockdownd_stop_SSL_session(): invalid argument!\n"); 139 log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_stop_SSL_session(): invalid argument!\n");
167 return; 140 return;
168 } 141 }
169 142
170 if (client->in_SSL) { 143 if (client->in_SSL) {
171 log_debug_msg("Stopping SSL Session\n"); 144 log_dbg_msg(DBGMASK_LOCKDOWND, "Stopping SSL Session\n");
172 iphone_lckd_stop_session(client); 145 iphone_lckd_stop_session(client);
173 log_debug_msg("Sending SSL close notify\n"); 146 log_dbg_msg(DBGMASK_LOCKDOWND, "Sending SSL close notify\n");
174 gnutls_bye(*client->ssl_session, GNUTLS_SHUT_RDWR); 147 gnutls_bye(*client->ssl_session, GNUTLS_SHUT_RDWR);
175 } 148 }
176 if (client->ssl_session) { 149 if (client->ssl_session) {
@@ -215,13 +188,13 @@ iphone_error_t iphone_lckd_free_client(iphone_lckd_client_t client)
215 * 188 *
216 * @return The number of bytes received 189 * @return The number of bytes received
217 */ 190 */
218iphone_error_t iphone_lckd_recv(iphone_lckd_client_t client, char **dump_data, uint32_t * recv_bytes) 191iphone_error_t iphone_lckd_recv(iphone_lckd_client_t client, plist_t * plist)
219{ 192{
220 if (!client || !dump_data || !recv_bytes) 193 if (!client || !plist || (plist && *plist))
221 return IPHONE_E_INVALID_ARG; 194 return IPHONE_E_INVALID_ARG;
222 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; 195 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
223 char *receive; 196 char *receive;
224 uint32 datalen = 0, bytes = 0; 197 uint32_t datalen = 0, bytes = 0;
225 198
226 if (!client->in_SSL) 199 if (!client->in_SSL)
227 ret = iphone_mux_recv(client->connection, (char *) &datalen, sizeof(datalen), &bytes); 200 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
240 if (bytes > 0) 213 if (bytes > 0)
241 ret = IPHONE_E_SUCCESS; 214 ret = IPHONE_E_SUCCESS;
242 } 215 }
243 *dump_data = receive; 216
244 *recv_bytes = bytes; 217 if (bytes <= 0) {
218 free(receive);
219 return IPHONE_E_NOT_ENOUGH_DATA;
220 }
221
222 log_dbg_msg(DBGMASK_LOCKDOWND, "Recv msg :\nsize : %i\nbuffer :\n%s\n", bytes, receive);
223 plist_from_xml(receive, bytes, plist);
224 free(receive);
225
226 if (!*plist)
227 ret = IPHONE_E_PLIST_ERROR;
228
245 return ret; 229 return ret;
246} 230}
247 231
248/** Sends lockdownd data to the iPhone 232/** Sends lockdownd data to the iPhone
249 * 233 *
250 * @note This function is low-level and should only be used if you need to send 234 * @note This function is low-level and should only be used if you need to send
251 * a new type of message. 235 * a new type of message.
252 * 236 *
253 * @param control The lockdownd client 237 * @param client The lockdownd client
254 * @param raw_data The null terminated string buffer to send 238 * @param plist The plist to send
255 * @param length The length of data to send
256 * 239 *
257 * @return The number of bytes sent 240 * @return an error code (IPHONE_E_SUCCESS on success)
258 */ 241 */
259iphone_error_t iphone_lckd_send(iphone_lckd_client_t client, char *raw_data, uint32_t length, uint32_t * sent_bytes) 242iphone_error_t iphone_lckd_send(iphone_lckd_client_t client, plist_t plist)
260{ 243{
261 if (!client || !raw_data || length == 0 || !sent_bytes) 244 if (!client || !plist)
262 return IPHONE_E_INVALID_ARG; 245 return IPHONE_E_INVALID_ARG;
263 char *real_query; 246 char *real_query;
264 int bytes; 247 int bytes;
248 char *XMLContent = NULL;
249 uint32_t length = 0;
265 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; 250 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
266 251
252 plist_to_xml(plist, &XMLContent, &length);
253 log_dbg_msg(DBGMASK_LOCKDOWND, "Send msg :\nsize : %i\nbuffer :\n%s\n", length, XMLContent);
254
255
267 real_query = (char *) malloc(sizeof(char) * (length + 4)); 256 real_query = (char *) malloc(sizeof(char) * (length + 4));
268 length = htonl(length); 257 length = htonl(length);
269 memcpy(real_query, &length, sizeof(length)); 258 memcpy(real_query, &length, sizeof(length));
270 memcpy(real_query + 4, raw_data, ntohl(length)); 259 memcpy(real_query + 4, XMLContent, ntohl(length));
271 log_debug_msg("lockdownd_send(): made the query, sending it along\n"); 260 free(XMLContent);
272 dump_debug_buffer("grpkt", real_query, ntohl(length) + 4); 261 log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_send(): made the query, sending it along\n");
273 262
274 if (!client->in_SSL) 263 if (!client->in_SSL)
275 ret = iphone_mux_send(client->connection, real_query, ntohl(length) + sizeof(length), &bytes); 264 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
277 gnutls_record_send(*client->ssl_session, real_query, ntohl(length) + sizeof(length)); 266 gnutls_record_send(*client->ssl_session, real_query, ntohl(length) + sizeof(length));
278 ret = IPHONE_E_SUCCESS; 267 ret = IPHONE_E_SUCCESS;
279 } 268 }
280 log_debug_msg("lockdownd_send(): sent it!\n"); 269 log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_send(): sent it!\n");
281 free(real_query); 270 free(real_query);
282 *sent_bytes = bytes; 271
283 return ret; 272 return ret;
284} 273}
285 274
286/** Initiates the handshake for the lockdown session. Part of the lockdownd handshake. 275/** Initiates the handshake for the lockdown session. Part of the lockdownd handshake.
287 * 276 *
288 * @note You most likely want lockdownd_init unless you are doing something special. 277 * @note You most likely want lockdownd_init unless you are doing something special.
289 * 278 *
290 * @param control The lockdownd client 279 * @param control The lockdownd client
@@ -295,49 +284,50 @@ iphone_error_t lockdownd_hello(iphone_lckd_client_t control)
295{ 284{
296 if (!control) 285 if (!control)
297 return IPHONE_E_INVALID_ARG; 286 return IPHONE_E_INVALID_ARG;
298 xmlDocPtr plist = new_plist(); 287
299 xmlNode *dict, *key;
300 char **dictionary;
301 int bytes = 0, i = 0;
302 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; 288 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
303 289
304 log_debug_msg("lockdownd_hello() called\n"); 290 plist_t dict = plist_new_dict();
305 dict = add_child_to_plist(plist, "dict", "\n", NULL, 0); 291 plist_add_sub_key_el(dict, "Request");
306 key = add_key_str_dict_element(plist, dict, "Request", "QueryType", 1); 292 plist_add_sub_string_el(dict, "QueryType");
307 char *XML_content;
308 uint32 length;
309 293
310 xmlDocDumpMemory(plist, (xmlChar **) & XML_content, &length); 294 log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_hello() called\n");
311 ret = iphone_lckd_send(control, XML_content, length, &bytes); 295 ret = iphone_lckd_send(control, dict);
312 296
313 xmlFree(XML_content); 297 plist_free(dict);
314 xmlFreeDoc(plist); 298 dict = NULL;
315 plist = NULL;
316 ret = iphone_lckd_recv(control, &XML_content, &bytes);
317 299
318 plist = xmlReadMemory(XML_content, bytes, NULL, NULL, 0); 300 ret = iphone_lckd_recv(control, &dict);
319 if (!plist) 301
320 return IPHONE_E_PLIST_ERROR; 302 if (IPHONE_E_SUCCESS != ret)
321 dict = xmlDocGetRootElement(plist); 303 return ret;
322 for (dict = dict->children; dict; dict = dict->next) { 304
323 if (!xmlStrcmp(dict->name, "dict")) 305 plist_t query_node = plist_find_node_by_string(dict, "QueryType");
324 break; 306 plist_t result_node = plist_get_next_sibling(query_node);
325 } 307 plist_t value_node = plist_get_next_sibling(result_node);
326 if (!dict) 308
327 return IPHONE_E_DICT_ERROR; 309 plist_type result_type = plist_get_node_type(result_node);
328 dictionary = read_dict_element_strings(dict); 310 plist_type value_type = plist_get_node_type(value_node);
329 xmlFreeDoc(plist); 311
330 free(XML_content); 312 if (result_type == PLIST_KEY && value_type == PLIST_STRING) {
331 313
332 for (i = 0; dictionary[i]; i += 2) { 314 char *result_value = NULL;
333 if (!strcmp(dictionary[i], "Result") && !strcmp(dictionary[i + 1], "Success")) { 315 char *value_value = NULL;
334 log_debug_msg("lockdownd_hello(): success\n"); 316
317 plist_get_key_val(result_node, &result_value);
318 plist_get_string_val(value_node, &value_value);
319
320 if (!strcmp(result_value, "Result") && !strcmp(value_value, "Success")) {
321 log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_hello(): success\n");
335 ret = IPHONE_E_SUCCESS; 322 ret = IPHONE_E_SUCCESS;
336 break;
337 } 323 }
324 free(result_value);
325 free(value_value);
338 } 326 }
339 327
340 free_dictionary(dictionary); 328 plist_free(dict);
329 dict = NULL;
330
341 return ret; 331 return ret;
342} 332}
343 333
@@ -350,73 +340,100 @@ iphone_error_t lockdownd_hello(iphone_lckd_client_t control)
350 * @return IPHONE_E_SUCCESS on success. 340 * @return IPHONE_E_SUCCESS on success.
351 */ 341 */
352iphone_error_t lockdownd_generic_get_value(iphone_lckd_client_t control, const char *req_key, const char *req_string, 342iphone_error_t lockdownd_generic_get_value(iphone_lckd_client_t control, const char *req_key, const char *req_string,
353 char **value) 343 gnutls_datum_t * value)
354{ 344{
355 if (!control || !req_key || !value || (value && *value)) 345 if (!control || !req_key || !value || value->data)
356 return IPHONE_E_INVALID_ARG; 346 return IPHONE_E_INVALID_ARG;
357 xmlDocPtr plist = new_plist(); 347
358 xmlNode *dict = NULL; 348 plist_t dict = NULL;
359 xmlNode *key = NULL;;
360 char **dictionary = NULL;
361 int bytes = 0, i = 0;
362 char *XML_content = NULL;
363 uint32 length = 0;
364 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; 349 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
365 350
366 /* Setup DevicePublicKey request plist */ 351 /* Setup DevicePublicKey request plist */
367 dict = add_child_to_plist(plist, "dict", "\n", NULL, 0); 352 dict = plist_new_dict();
368 key = add_key_str_dict_element(plist, dict, req_key, req_string, 1); 353 plist_add_sub_key_el(dict, req_key);
369 key = add_key_str_dict_element(plist, dict, "Request", "GetValue", 1); 354 plist_add_sub_string_el(dict, req_string);
370 xmlDocDumpMemory(plist, (xmlChar **) & XML_content, &length); 355 plist_add_sub_key_el(dict, "Request");
356 plist_add_sub_string_el(dict, "GetValue");
371 357
372 /* send to iPhone */ 358 /* send to iPhone */
373 ret = iphone_lckd_send(control, XML_content, length, &bytes); 359 ret = iphone_lckd_send(control, dict);
374 360
375 xmlFree(XML_content); 361 plist_free(dict);
376 xmlFreeDoc(plist); 362 dict = NULL;
377 plist = NULL;
378 363
379 if (ret != IPHONE_E_SUCCESS) 364 if (ret != IPHONE_E_SUCCESS)
380 return ret; 365 return ret;
381 366
382 /* Now get iPhone's answer */ 367 /* Now get iPhone's answer */
383 ret = iphone_lckd_recv(control, &XML_content, &bytes); 368 ret = iphone_lckd_recv(control, &dict);
384 369
385 if (ret != IPHONE_E_SUCCESS) 370 if (ret != IPHONE_E_SUCCESS)
386 return ret; 371 return ret;
387 372
388 plist = xmlReadMemory(XML_content, bytes, NULL, NULL, 0); 373 plist_t query_node = plist_find_node_by_string(dict, "GetValue");
389 if (!plist) 374 plist_t result_key_node = plist_get_next_sibling(query_node);
390 return IPHONE_E_PLIST_ERROR; 375 plist_t result_value_node = plist_get_next_sibling(result_key_node);
391 dict = xmlDocGetRootElement(plist);
392 for (dict = dict->children; dict; dict = dict->next) {
393 if (!xmlStrcmp(dict->name, "dict"))
394 break;
395 }
396 if (!dict)
397 return IPHONE_E_DICT_ERROR;
398 376
399 /* Parse xml to check success and to find public key */ 377 plist_type result_key_type = plist_get_node_type(result_key_node);
400 dictionary = read_dict_element_strings(dict); 378 plist_type result_value_type = plist_get_node_type(result_value_node);
401 xmlFreeDoc(plist);
402 free(XML_content);
403 379
404 int success = 0; 380 if (result_key_type == PLIST_KEY && result_value_type == PLIST_STRING) {
405 for (i = 0; dictionary[i]; i += 2) { 381
406 if (!strcmp(dictionary[i], "Result") && !strcmp(dictionary[i + 1], "Success")) { 382 char *result_key = NULL;
407 success = 1; 383 char *result_value = NULL;
408 } 384 ret = IPHONE_E_DICT_ERROR;
409 if (!strcmp(dictionary[i], "Value")) { 385
410 *value = strdup(dictionary[i + 1]); 386 plist_get_key_val(result_key_node, &result_key);
387 plist_get_string_val(result_value_node, &result_value);
388
389 if (!strcmp(result_key, "Result") && !strcmp(result_value, "Success")) {
390 log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_generic_get_value(): success\n");
391 ret = IPHONE_E_SUCCESS;
411 } 392 }
393 free(result_key);
394 free(result_value);
395 }
396 if (ret != IPHONE_E_SUCCESS) {
397 return ret;
412 } 398 }
413 399
414 if (dictionary) { 400 plist_t value_key_node = plist_find_node_by_key(dict, "Value");//plist_get_next_sibling(result_value_node);
415 free_dictionary(dictionary); 401 plist_t value_value_node = plist_get_next_sibling(value_key_node);
416 dictionary = NULL; 402
403 plist_type value_key_type = plist_get_node_type(value_key_node);
404
405 if (value_key_type == PLIST_KEY) {
406
407 char *result_key = NULL;
408 plist_get_key_val(value_key_node, &result_key);
409
410 if (!strcmp(result_key, "Value")) {
411 log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_generic_get_value(): success\n");
412
413 plist_type value_value_type = plist_get_node_type(value_value_node);
414 if (PLIST_STRING == value_value_type) {
415 char *value_value = NULL;
416 plist_get_string_val(value_value_node, &value_value);
417
418 value->data = value_value;
419 value->size = strlen(value_value);
420 ret = IPHONE_E_SUCCESS;
421 }
422
423 if (PLIST_DATA == value_value_type) {
424 char *value_value = NULL;
425 uint64_t size = 0;
426 plist_get_data_val(value_value_node, &value_value, &size);
427
428 value->data = value_value;
429 value->size = size;
430 ret = IPHONE_E_SUCCESS;
431 }
432 }
433 free(result_key);
417 } 434 }
418 if (success) 435
419 ret = IPHONE_E_SUCCESS; 436 plist_free(dict);
420 return ret; 437 return ret;
421} 438}
422 439
@@ -428,7 +445,10 @@ iphone_error_t lockdownd_generic_get_value(iphone_lckd_client_t control, const c
428 */ 445 */
429iphone_error_t lockdownd_get_device_uid(iphone_lckd_client_t control, char **uid) 446iphone_error_t lockdownd_get_device_uid(iphone_lckd_client_t control, char **uid)
430{ 447{
431 return lockdownd_generic_get_value(control, "Key", "UniqueDeviceID", uid); 448 gnutls_datum_t temp = { NULL, 0 };
449 iphone_error_t ret = lockdownd_generic_get_value(control, "Key", "UniqueDeviceID", &temp);
450 *uid = temp.data;
451 return ret;
432} 452}
433 453
434/** Askes for the device's public key. Part of the lockdownd handshake. 454/** 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
437 * 457 *
438 * @return 1 on success and 0 on failure. 458 * @return 1 on success and 0 on failure.
439 */ 459 */
440iphone_error_t lockdownd_get_device_public_key(iphone_lckd_client_t control, char **public_key) 460iphone_error_t lockdownd_get_device_public_key(iphone_lckd_client_t control, gnutls_datum_t * public_key)
441{ 461{
442 return lockdownd_generic_get_value(control, "Key", "DevicePublicKey", public_key); 462 return lockdownd_generic_get_value(control, "Key", "DevicePublicKey", public_key);
443} 463}
@@ -472,6 +492,7 @@ iphone_error_t iphone_lckd_new_client(iphone_device_t device, iphone_lckd_client
472 if (IPHONE_E_SUCCESS != ret) { 492 if (IPHONE_E_SUCCESS != ret) {
473 log_debug_msg("Device refused to send uid.\n"); 493 log_debug_msg("Device refused to send uid.\n");
474 } 494 }
495 log_debug_msg("Device uid: %s\n", uid);
475 496
476 host_id = get_host_id(); 497 host_id = get_host_id();
477 if (IPHONE_E_SUCCESS == ret && !host_id) { 498 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
487 uid = NULL; 508 uid = NULL;
488 } 509 }
489 510
490 ret = lockdownd_start_SSL_session(client_loc, host_id); 511 if (IPHONE_E_SUCCESS == ret) {
491 if (IPHONE_E_SUCCESS != ret) { 512 ret = lockdownd_start_SSL_session(client_loc, host_id);
492 ret = IPHONE_E_SSL_ERROR; 513 if (IPHONE_E_SUCCESS != ret) {
493 log_debug_msg("SSL Session opening failed.\n"); 514 ret = IPHONE_E_SSL_ERROR;
494 } 515 log_debug_msg("SSL Session opening failed.\n");
516 }
517
518 if (host_id) {
519 free(host_id);
520 host_id = NULL;
521 }
495 522
496 if (host_id) { 523 if (IPHONE_E_SUCCESS == ret)
497 free(host_id); 524 *client = client_loc;
498 host_id = NULL;
499 } 525 }
500 526
501 if (IPHONE_E_SUCCESS == ret)
502 *client = client_loc;
503 return ret; 527 return ret;
504} 528}
505 529
@@ -513,107 +537,92 @@ iphone_error_t iphone_lckd_new_client(iphone_device_t device, iphone_lckd_client
513iphone_error_t lockdownd_pair_device(iphone_lckd_client_t control, char *uid, char *host_id) 537iphone_error_t lockdownd_pair_device(iphone_lckd_client_t control, char *uid, char *host_id)
514{ 538{
515 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; 539 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
516 xmlDocPtr plist = new_plist(); 540 plist_t dict = NULL;
517 xmlNode *dict = NULL; 541 plist_t dict_record = NULL;
518 xmlNode *dictRecord = NULL; 542
519 char **dictionary = NULL; 543 gnutls_datum_t device_cert = { NULL, 0 };
520 int bytes = 0, i = 0; 544 gnutls_datum_t host_cert = { NULL, 0 };
521 char *XML_content = NULL; 545 gnutls_datum_t root_cert = { NULL, 0 };
522 uint32 length = 0; 546 gnutls_datum_t public_key = { NULL, 0 };
523 547
524 char *device_cert_b64 = NULL; 548 ret = lockdownd_get_device_public_key(control, &public_key);
525 char *host_cert_b64 = NULL;
526 char *root_cert_b64 = NULL;
527 char *public_key_b64 = NULL;
528
529 ret = lockdownd_get_device_public_key(control, &public_key_b64);
530 if (ret != IPHONE_E_SUCCESS) { 549 if (ret != IPHONE_E_SUCCESS) {
531 log_debug_msg("Device refused to send public key.\n"); 550 log_debug_msg("Device refused to send public key.\n");
532 return ret; 551 return ret;
533 } 552 }
553 log_debug_msg("device public key :\n %s.\n", public_key.data);
534 554
535 ret = lockdownd_gen_pair_cert(public_key_b64, &device_cert_b64, &host_cert_b64, &root_cert_b64); 555 ret = lockdownd_gen_pair_cert(public_key, &device_cert, &host_cert, &root_cert);
536 if (ret != IPHONE_E_SUCCESS) { 556 if (ret != IPHONE_E_SUCCESS) {
537 free(public_key_b64); 557 free(public_key.data);
538 return ret; 558 return ret;
539 } 559 }
540 560
541 /* Setup Pair request plist */ 561 /* Setup Pair request plist */
542 dict = add_child_to_plist(plist, "dict", "\n", NULL, 0); 562 dict = plist_new_dict();
543 dictRecord = add_key_dict_node(plist, dict, "PairRecord", "\n", 1); 563 plist_add_sub_key_el(dict, "PairRecord");
544 //dictRecord = add_child_to_plist(plist, "dict", "\n", NULL, 1); 564 dict_record = plist_new_dict();
545 add_key_data_dict_element(plist, dictRecord, "DeviceCertificate", device_cert_b64, 2); 565 plist_add_sub_node(dict, dict_record);
546 add_key_data_dict_element(plist, dictRecord, "HostCertificate", host_cert_b64, 2); 566 plist_add_sub_key_el(dict_record, "DeviceCertificate");
547 add_key_str_dict_element(plist, dictRecord, "HostID", host_id, 2); 567 plist_add_sub_data_el(dict_record, (const char*)device_cert.data, device_cert.size);
548 add_key_data_dict_element(plist, dictRecord, "RootCertificate", root_cert_b64, 2); 568 plist_add_sub_key_el(dict_record, "HostCertificate");
549 add_key_str_dict_element(plist, dict, "Request", "Pair", 1); 569 plist_add_sub_data_el(dict_record, (const char*)host_cert.data, host_cert.size);
550 570 plist_add_sub_key_el(dict_record, "HostID");
551 xmlDocDumpMemory(plist, (xmlChar **) & XML_content, &length); 571 plist_add_sub_string_el(dict_record, host_id);
552 572 plist_add_sub_key_el(dict_record, "RootCertificate");
553 printf("XML Pairing request : %s\n", XML_content); 573 plist_add_sub_data_el(dict_record, (const char*)root_cert.data, root_cert.size);
574 plist_add_sub_key_el(dict, "Request");
575 plist_add_sub_string_el(dict, "Pair");
554 576
555 /* send to iPhone */ 577 /* send to iPhone */
556 ret = iphone_lckd_send(control, XML_content, length, &bytes); 578 ret = iphone_lckd_send(control, dict);
557 579 plist_free(dict);
558 xmlFree(XML_content); 580 dict = NULL;
559 xmlFreeDoc(plist);
560 plist = NULL;
561 581
562 if (ret != IPHONE_E_SUCCESS) 582 if (ret != IPHONE_E_SUCCESS)
563 return ret; 583 return ret;
564 584
565 /* Now get iPhone's answer */ 585 /* Now get iPhone's answer */
566 ret = iphone_lckd_recv(control, &XML_content, &bytes); 586 ret = iphone_lckd_recv(control, &dict);
567 587
568 if (ret != IPHONE_E_SUCCESS) 588 if (ret != IPHONE_E_SUCCESS)
569 return ret; 589 return ret;
570 590
571 log_debug_msg("lockdown_pair_device: iPhone's response to our pair request:\n"); 591 plist_t query_node = plist_find_node_by_string(dict, "Pair");
572 log_debug_msg(XML_content); 592 plist_t result_key_node = plist_get_next_sibling(query_node);
573 log_debug_msg("\n\n"); 593 plist_t result_value_node = plist_get_next_sibling(result_key_node);
574 594
575 plist = xmlReadMemory(XML_content, bytes, NULL, NULL, 0); 595 plist_type result_key_type = plist_get_node_type(result_key_node);
576 if (!plist) { 596 plist_type result_value_type = plist_get_node_type(result_value_node);
577 free(public_key_b64);
578 return IPHONE_E_PLIST_ERROR;
579 }
580 dict = xmlDocGetRootElement(plist);
581 for (dict = dict->children; dict; dict = dict->next) {
582 if (!xmlStrcmp(dict->name, "dict"))
583 break;
584 }
585 if (!dict) {
586 free(public_key_b64);
587 return IPHONE_E_DICT_ERROR;
588 }
589 597
590 /* Parse xml to check success and to find public key */ 598 if (result_key_type == PLIST_KEY && result_value_type == PLIST_STRING) {
591 dictionary = read_dict_element_strings(dict);
592 xmlFreeDoc(plist);
593 free(XML_content);
594 599
595 int success = 0; 600 char *result_key = NULL;
596 for (i = 0; dictionary[i]; i += 2) { 601 char *result_value = NULL;
597 if (!strcmp(dictionary[i], "Result") && !strcmp(dictionary[i + 1], "Success")) { 602
598 success = 1; 603 plist_get_key_val(result_key_node, &result_key);
604 plist_get_string_val(result_value_node, &result_value);
605
606 if (!strcmp(result_key, "Result") && !strcmp(result_value, "Success")) {
607 ret = IPHONE_E_SUCCESS;
599 } 608 }
600 }
601 609
602 if (dictionary) { 610 free(result_key);
603 free_dictionary(dictionary); 611 free(result_value);
604 dictionary = NULL;
605 } 612 }
613 plist_free(dict);
614 dict = NULL;
606 615
607 /* store public key in config if pairing succeeded */ 616 /* store public key in config if pairing succeeded */
608 if (success) { 617 if (ret == IPHONE_E_SUCCESS) {
609 log_debug_msg("lockdownd_pair_device: pair success\n"); 618 log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_pair_device: pair success\n");
610 store_device_public_key(uid, public_key_b64); 619 store_device_public_key(uid, public_key);
611 ret = IPHONE_E_SUCCESS; 620 ret = IPHONE_E_SUCCESS;
612 } else { 621 } else {
613 log_debug_msg("lockdownd_pair_device: pair failure\n"); 622 log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_pair_device: pair failure\n");
614 ret = IPHONE_E_PAIRING_FAILED; 623 ret = IPHONE_E_PAIRING_FAILED;
615 } 624 }
616 free(public_key_b64); 625 free(public_key.data);
617 return ret; 626 return ret;
618} 627}
619 628
@@ -626,81 +635,71 @@ iphone_error_t lockdownd_pair_device(iphone_lckd_client_t control, char *uid, ch
626void lockdownd_close(iphone_lckd_client_t control) 635void lockdownd_close(iphone_lckd_client_t control)
627{ 636{
628 if (!control) 637 if (!control)
629 return; // IPHONE_E_INVALID_ARG; 638 return; //IPHONE_E_INVALID_ARG;
630 xmlDocPtr plist = new_plist(); 639
631 xmlNode *dict, *key;
632 char **dictionary;
633 int bytes = 0, i = 0;
634 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; 640 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
635 641
636 log_debug_msg("lockdownd_close() called\n"); 642 plist_t dict = plist_new_dict();
637 dict = add_child_to_plist(plist, "dict", "\n", NULL, 0); 643 plist_add_sub_key_el(dict, "Request");
638 key = add_key_str_dict_element(plist, dict, "Request", "Goodbye", 1); 644 plist_add_sub_string_el(dict, "Goodbye");
639 char *XML_content;
640 uint32 length;
641 645
642 xmlDocDumpMemory(plist, (xmlChar **) & XML_content, &length); 646 log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_close() called\n");
643 ret = iphone_lckd_send(control, XML_content, length, &bytes);
644 647
645 xmlFree(XML_content); 648 ret = iphone_lckd_send(control, dict);
646 xmlFreeDoc(plist); 649 plist_free(dict);
647 plist = NULL; 650 dict = NULL;
648 ret = iphone_lckd_recv(control, &XML_content, &bytes); 651
652 ret = iphone_lckd_recv(control, &dict);
649 653
650 plist = xmlReadMemory(XML_content, bytes, NULL, NULL, 0);
651 if (!plist) {
652 log_debug_msg("lockdownd_close(): IPHONE_E_PLIST_ERROR\n");
653 return; //IPHONE_E_PLIST_ERROR;
654 }
655 dict = xmlDocGetRootElement(plist);
656 for (dict = dict->children; dict; dict = dict->next) {
657 if (!xmlStrcmp(dict->name, "dict"))
658 break;
659 }
660 if (!dict) { 654 if (!dict) {
661 log_debug_msg("lockdownd_close(): IPHONE_E_DICT_ERROR\n"); 655 log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_close(): IPHONE_E_PLIST_ERROR\n");
662 return; //IPHONE_E_DICT_ERROR; 656 return; // IPHONE_E_PLIST_ERROR;
663 } 657 }
664 dictionary = read_dict_element_strings(dict);
665 xmlFreeDoc(plist);
666 free(XML_content);
667 658
668 for (i = 0; dictionary[i]; i += 2) { 659 plist_t query_node = plist_find_node_by_string(dict, "Goodbye");
669 if (!strcmp(dictionary[i], "Result") && !strcmp(dictionary[i + 1], "Success")) { 660 plist_t result_node = plist_get_next_sibling(query_node);
670 log_debug_msg("lockdownd_close(): success\n"); 661 plist_t value_node = plist_get_next_sibling(result_node);
662
663 plist_type result_type = plist_get_node_type(result_node);
664 plist_type value_type = plist_get_node_type(value_node);
665
666 if (result_type == PLIST_KEY && value_type == PLIST_STRING) {
667 char *result_value = NULL;
668 char *value_value = NULL;
669
670 plist_get_key_val(result_node, &result_value);
671 plist_get_string_val(value_node, &value_value);
672
673 if (!strcmp(result_value, "Result") && !strcmp(value_value, "Success")) {
674 log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_close(): success\n");
671 ret = IPHONE_E_SUCCESS; 675 ret = IPHONE_E_SUCCESS;
672 break;
673 } 676 }
677 free(result_value);
678 free(value_value);
674 } 679 }
675 680 plist_free(dict);
676 free_dictionary(dictionary); 681 dict = NULL;
677 return; //ret; 682 return; // ret;
678} 683}
679 684
680/** Generates the device certificate from the public key as well as the host 685/** Generates the device certificate from the public key as well as the host
681 * and root certificates. 686 * and root certificates.
682 * 687 *
683 * @return IPHONE_E_SUCCESS on success. 688 * @return IPHONE_E_SUCCESS on success.
684 */ 689 */
685iphone_error_t lockdownd_gen_pair_cert(char *public_key_b64, char **device_cert_b64, char **host_cert_b64, 690iphone_error_t lockdownd_gen_pair_cert(gnutls_datum_t public_key, gnutls_datum_t * odevice_cert,
686 char **root_cert_b64) 691 gnutls_datum_t * ohost_cert, gnutls_datum_t * oroot_cert)
687{ 692{
688 if (!public_key_b64 || !device_cert_b64 || !host_cert_b64 || !root_cert_b64) 693 if (!public_key.data || !odevice_cert || !ohost_cert || !oroot_cert)
689 return IPHONE_E_INVALID_ARG; 694 return IPHONE_E_INVALID_ARG;
690 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; 695 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
691 696
692 gnutls_datum_t modulus = { NULL, 0 }; 697 gnutls_datum_t modulus = { NULL, 0 };
693 gnutls_datum_t exponent = { NULL, 0 }; 698 gnutls_datum_t exponent = { NULL, 0 };
694 699
695 /* first decode base64 public_key */
696 gnutls_datum_t pem_pub_key;
697 gsize decoded_size;
698 pem_pub_key.data = g_base64_decode(public_key_b64, &decoded_size);
699 pem_pub_key.size = decoded_size;
700
701 /* now decode the PEM encoded key */ 700 /* now decode the PEM encoded key */
702 gnutls_datum_t der_pub_key; 701 gnutls_datum_t der_pub_key;
703 if (GNUTLS_E_SUCCESS == gnutls_pem_base64_decode_alloc("RSA PUBLIC KEY", &pem_pub_key, &der_pub_key)) { 702 if (GNUTLS_E_SUCCESS == gnutls_pem_base64_decode_alloc("RSA PUBLIC KEY", &public_key, &der_pub_key)) {
704 703
705 /* initalize asn.1 parser */ 704 /* initalize asn.1 parser */
706 ASN1_TYPE pkcs1 = ASN1_TYPE_EMPTY; 705 ASN1_TYPE pkcs1 = ASN1_TYPE_EMPTY;
@@ -736,7 +735,7 @@ iphone_error_t lockdownd_gen_pair_cert(char *public_key_b64, char **device_cert_
736 gnutls_global_init(); 735 gnutls_global_init();
737 gnutls_datum_t essentially_null = { strdup("abababababababab"), strlen("abababababababab") }; 736 gnutls_datum_t essentially_null = { strdup("abababababababab"), strlen("abababababababab") };
738 737
739 gnutls_x509_privkey_t fake_privkey, root_privkey; 738 gnutls_x509_privkey_t fake_privkey, root_privkey, host_privkey;
740 gnutls_x509_crt_t dev_cert, root_cert, host_cert; 739 gnutls_x509_crt_t dev_cert, root_cert, host_cert;
741 740
742 gnutls_x509_privkey_init(&fake_privkey); 741 gnutls_x509_privkey_init(&fake_privkey);
@@ -749,49 +748,50 @@ iphone_error_t lockdownd_gen_pair_cert(char *public_key_b64, char **device_cert_
749 &essentially_null, &essentially_null)) { 748 &essentially_null, &essentially_null)) {
750 749
751 gnutls_x509_privkey_init(&root_privkey); 750 gnutls_x509_privkey_init(&root_privkey);
751 gnutls_x509_privkey_init(&host_privkey);
752 752
753 /* get root cert */ 753 ret = get_keys_and_certs( root_privkey, root_cert, host_privkey, host_cert);
754 gnutls_datum_t pem_root_cert = { NULL, 0 };
755 get_root_certificate(&pem_root_cert);
756 if (GNUTLS_E_SUCCESS != gnutls_x509_crt_import(root_cert, &pem_root_cert, GNUTLS_X509_FMT_PEM))
757 ret = IPHONE_E_SSL_ERROR;
758
759 /* get host cert */
760 gnutls_datum_t pem_host_cert = { NULL, 0 };
761 get_host_certificate(&pem_host_cert);
762 if (GNUTLS_E_SUCCESS != gnutls_x509_crt_import(host_cert, &pem_host_cert, GNUTLS_X509_FMT_PEM))
763 ret = IPHONE_E_SSL_ERROR;
764
765 /* get root private key */
766 gnutls_datum_t pem_root_priv = { NULL, 0 };
767 get_root_private_key(&pem_root_priv);
768 if (GNUTLS_E_SUCCESS != gnutls_x509_privkey_import(root_privkey, &pem_root_priv, GNUTLS_X509_FMT_PEM))
769 ret = IPHONE_E_SSL_ERROR;
770
771 /* generate device certificate */
772 gnutls_x509_crt_set_key(dev_cert, fake_privkey);
773 gnutls_x509_crt_set_serial(dev_cert, "\x00", 1);
774 gnutls_x509_crt_set_version(dev_cert, 3);
775 gnutls_x509_crt_set_ca_status(dev_cert, 0);
776 gnutls_x509_crt_set_activation_time(dev_cert, time(NULL));
777 gnutls_x509_crt_set_expiration_time(dev_cert, time(NULL) + (60 * 60 * 24 * 365 * 10));
778 gnutls_x509_crt_sign(dev_cert, root_cert, root_privkey);
779 754
780 if (IPHONE_E_SUCCESS == ret) { 755 if (IPHONE_E_SUCCESS == ret) {
781 /* if everything went well, export in PEM format */ 756
782 gnutls_datum_t dev_pem = { NULL, 0 }; 757 /* generate device certificate */
783 gnutls_x509_crt_export(dev_cert, GNUTLS_X509_FMT_PEM, NULL, &dev_pem.size); 758 gnutls_x509_crt_set_key(dev_cert, fake_privkey);
784 dev_pem.data = gnutls_malloc(dev_pem.size); 759 gnutls_x509_crt_set_serial(dev_cert, "\x00", 1);
785 gnutls_x509_crt_export(dev_cert, GNUTLS_X509_FMT_PEM, dev_pem.data, &dev_pem.size); 760 gnutls_x509_crt_set_version(dev_cert, 3);
786 761 gnutls_x509_crt_set_ca_status(dev_cert, 0);
787 /* now encode certificates for output */ 762 gnutls_x509_crt_set_activation_time(dev_cert, time(NULL));
788 *device_cert_b64 = g_base64_encode(dev_pem.data, dev_pem.size); 763 gnutls_x509_crt_set_expiration_time(dev_cert, time(NULL) + (60 * 60 * 24 * 365 * 10));
789 *host_cert_b64 = g_base64_encode(pem_host_cert.data, pem_host_cert.size); 764 gnutls_x509_crt_sign(dev_cert, root_cert, root_privkey);
790 *root_cert_b64 = g_base64_encode(pem_root_cert.data, pem_root_cert.size); 765
766 if (IPHONE_E_SUCCESS == ret) {
767 /* if everything went well, export in PEM format */
768 gnutls_datum_t dev_pem = { NULL, 0 };
769 gnutls_x509_crt_export(dev_cert, GNUTLS_X509_FMT_PEM, NULL, &dev_pem.size);
770 dev_pem.data = gnutls_malloc(dev_pem.size);
771 gnutls_x509_crt_export(dev_cert, GNUTLS_X509_FMT_PEM, dev_pem.data, &dev_pem.size);
772
773 gnutls_datum_t pem_root_cert = { NULL, 0 };
774 gnutls_datum_t pem_host_cert = { NULL, 0 };
775
776 if ( IPHONE_E_SUCCESS == get_certs_as_pem(&pem_root_cert, &pem_host_cert) ) {
777 /* copy buffer for output */
778 odevice_cert->data = malloc(dev_pem.size);
779 memcpy(odevice_cert->data, dev_pem.data, dev_pem.size);
780 odevice_cert->size = dev_pem.size;
781
782 ohost_cert->data = malloc(pem_host_cert.size);
783 memcpy(ohost_cert->data, pem_host_cert.data, pem_host_cert.size);
784 ohost_cert->size = pem_host_cert.size;
785
786 oroot_cert->data = malloc(pem_root_cert.size);
787 memcpy(oroot_cert->data, pem_root_cert.data, pem_root_cert.size);
788 oroot_cert->size = pem_root_cert.size;
789
790 g_free(pem_root_cert.data);
791 g_free(pem_host_cert.data);
792 }
793 }
791 } 794 }
792 gnutls_free(pem_root_priv.data);
793 gnutls_free(pem_root_cert.data);
794 gnutls_free(pem_host_cert.data);
795 } 795 }
796 } 796 }
797 797
@@ -799,7 +799,6 @@ iphone_error_t lockdownd_gen_pair_cert(char *public_key_b64, char **device_cert_
799 gnutls_free(exponent.data); 799 gnutls_free(exponent.data);
800 800
801 gnutls_free(der_pub_key.data); 801 gnutls_free(der_pub_key.data);
802 g_free(pem_pub_key.data);
803 802
804 return ret; 803 return ret;
805} 804}
@@ -813,129 +812,127 @@ iphone_error_t lockdownd_gen_pair_cert(char *public_key_b64, char **device_cert_
813 */ 812 */
814iphone_error_t lockdownd_start_SSL_session(iphone_lckd_client_t control, const char *HostID) 813iphone_error_t lockdownd_start_SSL_session(iphone_lckd_client_t control, const char *HostID)
815{ 814{
816 xmlDocPtr plist = new_plist(); 815 plist_t dict = NULL;
817 xmlNode *dict = add_child_to_plist(plist, "dict", "\n", NULL, 0); 816 uint32_t return_me = 0;
818 xmlNode *key;
819 char *what2send = NULL, **dictionary = NULL;
820 uint32 len = 0, bytes = 0, return_me = 0, i = 0;
821 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
822 // end variables
823 817
818 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
824 control->session_id[0] = '\0'; 819 control->session_id[0] = '\0';
825 820
826 key = add_key_str_dict_element(plist, dict, "HostID", HostID, 1); 821 /* Setup DevicePublicKey request plist */
827 if (!key) { 822 dict = plist_new_dict();
828 log_debug_msg("Couldn't add a key.\n"); 823 plist_add_sub_key_el(dict, "HostID");
829 xmlFreeDoc(plist); 824 plist_add_sub_string_el(dict, HostID);
830 return IPHONE_E_DICT_ERROR; 825 plist_add_sub_key_el(dict, "Request");
831 } 826 plist_add_sub_string_el(dict, "StartSession");
832 key = add_key_str_dict_element(plist, dict, "Request", "StartSession", 1);
833 if (!key) {
834 log_debug_msg("Couldn't add a key.\n");
835 xmlFreeDoc(plist);
836 return IPHONE_E_DICT_ERROR;
837 }
838
839 xmlDocDumpMemory(plist, (xmlChar **) & what2send, &len);
840 ret = iphone_lckd_send(control, what2send, len, &bytes);
841 827
842 xmlFree(what2send); 828 ret = iphone_lckd_send(control, dict);
843 xmlFreeDoc(plist); 829 plist_free(dict);
830 dict = NULL;
844 831
845 if (ret != IPHONE_E_SUCCESS) 832 if (ret != IPHONE_E_SUCCESS)
846 return ret; 833 return ret;
847 834
848 if (bytes > 0) { 835 ret = iphone_lckd_recv(control, &dict);
849 ret = iphone_lckd_recv(control, &what2send, &len); 836
850 plist = xmlReadMemory(what2send, len, NULL, NULL, 0); 837 if (!dict)
851 dict = xmlDocGetRootElement(plist); 838 return IPHONE_E_PLIST_ERROR;
852 if (!dict) 839
853 return IPHONE_E_DICT_ERROR; 840 plist_t query_node = plist_find_node_by_string(dict, "StartSession");
854 for (dict = dict->children; dict; dict = dict->next) { 841 plist_t result_key_node = plist_get_next_sibling(query_node);
855 if (!xmlStrcmp(dict->name, "dict")) 842 plist_t result_value_node = plist_get_next_sibling(result_key_node);
856 break; 843
857 } 844 plist_type result_key_type = plist_get_node_type(result_key_node);
858 dictionary = read_dict_element_strings(dict); 845 plist_type result_value_type = plist_get_node_type(result_value_node);
859 xmlFreeDoc(plist); 846
860 free(what2send); 847 if (result_key_type == PLIST_KEY && result_value_type == PLIST_STRING) {
848 char *result_key = NULL;
849 char *result_value = NULL;
850
851 plist_get_key_val(result_key_node, &result_key);
852 plist_get_string_val(result_value_node, &result_value);
853
861 ret = IPHONE_E_SSL_ERROR; 854 ret = IPHONE_E_SSL_ERROR;
862 for (i = 0; dictionary[i]; i += 2) { 855 if (!strcmp(result_key, "Result") && !strcmp(result_value, "Success")) {
863 if (!strcmp(dictionary[i], "Result") && !strcmp(dictionary[i + 1], "Success")) { 856 // Set up GnuTLS...
864 // Set up GnuTLS... 857 //gnutls_anon_client_credentials_t anoncred;
865 //gnutls_anon_client_credentials_t anoncred; 858 gnutls_certificate_credentials_t xcred;
866 gnutls_certificate_credentials_t xcred; 859
867 860 log_dbg_msg(DBGMASK_LOCKDOWND, "We started the session OK, now trying GnuTLS\n");
868 log_debug_msg("We started the session OK, now trying GnuTLS\n"); 861 errno = 0;
869 errno = 0; 862 gnutls_global_init();
870 gnutls_global_init(); 863 //gnutls_anon_allocate_client_credentials(&anoncred);
871 //gnutls_anon_allocate_client_credentials(&anoncred); 864 gnutls_certificate_allocate_credentials(&xcred);
872 gnutls_certificate_allocate_credentials(&xcred); 865 gnutls_certificate_set_x509_trust_file(xcred, "hostcert.pem", GNUTLS_X509_FMT_PEM);
873 gnutls_certificate_set_x509_trust_file(xcred, "hostcert.pem", GNUTLS_X509_FMT_PEM); 866 gnutls_init(control->ssl_session, GNUTLS_CLIENT);
874 gnutls_init(control->ssl_session, GNUTLS_CLIENT); 867 {
875 { 868 int protocol_priority[16] = { GNUTLS_SSL3, 0 };
876 int protocol_priority[16] = { GNUTLS_SSL3, 0 }; 869 int kx_priority[16] = { GNUTLS_KX_ANON_DH, GNUTLS_KX_RSA, 0 };
877 int kx_priority[16] = { GNUTLS_KX_ANON_DH, GNUTLS_KX_RSA, 0 }; 870 int cipher_priority[16] = { GNUTLS_CIPHER_AES_128_CBC, GNUTLS_CIPHER_AES_256_CBC, 0 };
878 int cipher_priority[16] = { GNUTLS_CIPHER_AES_128_CBC, GNUTLS_CIPHER_AES_256_CBC, 0 }; 871 int mac_priority[16] = { GNUTLS_MAC_SHA1, GNUTLS_MAC_MD5, 0 };
879 int mac_priority[16] = { GNUTLS_MAC_SHA1, GNUTLS_MAC_MD5, 0 }; 872 int comp_priority[16] = { GNUTLS_COMP_NULL, 0 };
880 int comp_priority[16] = { GNUTLS_COMP_NULL, 0 }; 873
881 874 gnutls_cipher_set_priority(*control->ssl_session, cipher_priority);
882 gnutls_cipher_set_priority(*control->ssl_session, cipher_priority); 875 gnutls_compression_set_priority(*control->ssl_session, comp_priority);
883 gnutls_compression_set_priority(*control->ssl_session, comp_priority); 876 gnutls_kx_set_priority(*control->ssl_session, kx_priority);
884 gnutls_kx_set_priority(*control->ssl_session, kx_priority); 877 gnutls_protocol_set_priority(*control->ssl_session, protocol_priority);
885 gnutls_protocol_set_priority(*control->ssl_session, protocol_priority); 878 gnutls_mac_set_priority(*control->ssl_session, mac_priority);
886 gnutls_mac_set_priority(*control->ssl_session, mac_priority);
887 879
888 } 880 }
889 gnutls_credentials_set(*control->ssl_session, GNUTLS_CRD_CERTIFICATE, xcred); // this part is killing me. 881 gnutls_credentials_set(*control->ssl_session, GNUTLS_CRD_CERTIFICATE, xcred); // this part is killing me.
890 882
891 log_debug_msg("GnuTLS step 1...\n"); 883 log_dbg_msg(DBGMASK_LOCKDOWND, "GnuTLS step 1...\n");
892 gnutls_transport_set_ptr(*control->ssl_session, (gnutls_transport_ptr_t) control); 884 gnutls_transport_set_ptr(*control->ssl_session, (gnutls_transport_ptr_t) control);
893 log_debug_msg("GnuTLS step 2...\n"); 885 log_dbg_msg(DBGMASK_LOCKDOWND, "GnuTLS step 2...\n");
894 gnutls_transport_set_push_function(*control->ssl_session, (gnutls_push_func) & lockdownd_secuwrite); 886 gnutls_transport_set_push_function(*control->ssl_session, (gnutls_push_func) & lockdownd_secuwrite);
895 log_debug_msg("GnuTLS step 3...\n"); 887 log_dbg_msg(DBGMASK_LOCKDOWND, "GnuTLS step 3...\n");
896 gnutls_transport_set_pull_function(*control->ssl_session, (gnutls_pull_func) & lockdownd_securead); 888 gnutls_transport_set_pull_function(*control->ssl_session, (gnutls_pull_func) & lockdownd_securead);
897 log_debug_msg("GnuTLS step 4 -- now handshaking...\n"); 889 log_dbg_msg(DBGMASK_LOCKDOWND, "GnuTLS step 4 -- now handshaking...\n");
898 890
899 if (errno) 891 if (errno)
900 log_debug_msg("WARN: errno says %s before handshake!\n", strerror(errno)); 892 log_dbg_msg(DBGMASK_LOCKDOWND, "WARN: errno says %s before handshake!\n", strerror(errno));
901 return_me = gnutls_handshake(*control->ssl_session); 893 return_me = gnutls_handshake(*control->ssl_session);
902 log_debug_msg("GnuTLS handshake done...\n"); 894 log_dbg_msg(DBGMASK_LOCKDOWND, "GnuTLS handshake done...\n");
903 895
904 if (return_me != GNUTLS_E_SUCCESS) { 896 if (return_me != GNUTLS_E_SUCCESS) {
905 log_debug_msg("GnuTLS reported something wrong.\n"); 897 log_dbg_msg(DBGMASK_LOCKDOWND, "GnuTLS reported something wrong.\n");
906 gnutls_perror(return_me); 898 gnutls_perror(return_me);
907 log_debug_msg("oh.. errno says %s\n", strerror(errno)); 899 log_dbg_msg(DBGMASK_LOCKDOWND, "oh.. errno says %s\n", strerror(errno));
908 return IPHONE_E_SSL_ERROR; 900 return IPHONE_E_SSL_ERROR;
909 } else { 901 } else {
910 control->in_SSL = 1; 902 control->in_SSL = 1;
911 ret = IPHONE_E_SUCCESS; 903 ret = IPHONE_E_SUCCESS;
912 }
913 } else if (!strcmp(dictionary[i], "SessionID")) {
914 // we need to store the session ID for StopSession
915 strcpy(control->session_id, dictionary[i + 1]);
916 log_debug_msg("SessionID: %s\n", control->session_id);
917 free_dictionary(dictionary);
918 return ret;
919 } 904 }
920 } 905 }
921 if (ret == IPHONE_E_SUCCESS) { 906 }
922 log_debug_msg("Failed to get SessionID!\n"); 907 //store session id
923 return ret; 908 plist_t session_node = plist_find_node_by_key(dict, "SessionID");
924 } 909 if (session_node) {
910
911 plist_t session_node_val = plist_get_next_sibling(session_node);
912 plist_type session_node_val_type = plist_get_node_type(session_node_val);
913
914 if (session_node_val_type == PLIST_STRING) {
925 915
926 log_debug_msg("Apparently failed negotiating with lockdownd.\n"); 916 char *session_id = NULL;
927 log_debug_msg("Responding dictionary: \n"); 917 plist_get_string_val(session_node_val, &session_id);
928 for (i = 0; dictionary[i]; i += 2) { 918
929 log_debug_msg("\t%s: %s\n", dictionary[i], dictionary[i + 1]); 919 if (session_node_val_type == PLIST_STRING && session_id) {
920 // we need to store the session ID for StopSession
921 strcpy(control->session_id, session_id);
922 log_dbg_msg(DBGMASK_LOCKDOWND, "SessionID: %s\n", control->session_id);
923 }
924 free(session_id);
930 } 925 }
926 } else
927 log_dbg_msg(DBGMASK_LOCKDOWND, "Failed to get SessionID!\n");
928 plist_free(dict);
929 dict = NULL;
931 930
931 if (ret == IPHONE_E_SUCCESS)
932 return ret;
932 933
933 free_dictionary(dictionary); 934 log_dbg_msg(DBGMASK_LOCKDOWND, "Apparently failed negotiating with lockdownd.\n");
934 return IPHONE_E_SSL_ERROR; 935 return IPHONE_E_SSL_ERROR;
935 } else {
936 log_debug_msg("Didn't get enough bytes.\n");
937 return IPHONE_E_NOT_ENOUGH_DATA;
938 }
939} 936}
940 937
941/** gnutls callback for writing data to the iPhone. 938/** gnutls callback for writing data to the iPhone.
@@ -951,10 +948,10 @@ ssize_t lockdownd_secuwrite(gnutls_transport_ptr_t transport, char *buffer, size
951 int bytes = 0; 948 int bytes = 0;
952 iphone_lckd_client_t control; 949 iphone_lckd_client_t control;
953 control = (iphone_lckd_client_t) transport; 950 control = (iphone_lckd_client_t) transport;
954 log_debug_msg("lockdownd_secuwrite() called\n"); 951 log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_secuwrite() called\n");
955 log_debug_msg("pre-send\nlength = %zi\n", length); 952 log_dbg_msg(DBGMASK_LOCKDOWND, "pre-send\nlength = %zi\n", length);
956 iphone_mux_send(control->connection, buffer, length, &bytes); 953 iphone_mux_send(control->connection, buffer, length, &bytes);
957 log_debug_msg("post-send\nsent %i bytes\n", bytes); 954 log_dbg_msg(DBGMASK_LOCKDOWND, "post-send\nsent %i bytes\n", bytes);
958 955
959 dump_debug_buffer("sslpacketwrite.out", buffer, length); 956 dump_debug_buffer("sslpacketwrite.out", buffer, length);
960 return bytes; 957 return bytes;
@@ -1038,86 +1035,72 @@ iphone_error_t iphone_lckd_start_service(iphone_lckd_client_t client, const char
1038 if (!client->in_SSL && !lockdownd_start_SSL_session(client, host_id)) 1035 if (!client->in_SSL && !lockdownd_start_SSL_session(client, host_id))
1039 return IPHONE_E_SSL_ERROR; 1036 return IPHONE_E_SSL_ERROR;
1040 1037
1041 char *XML_query, **dictionary; 1038 plist_t dict = NULL;
1042 uint32 length, i = 0, port_loc = 0, bytes = 0; 1039 uint32_t port_loc = 0;
1043 uint8 result = 0;
1044 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; 1040 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
1045 1041
1046 free(host_id); 1042 free(host_id);
1047 host_id = NULL; 1043 host_id = NULL;
1048 1044
1049 xmlDocPtr plist = new_plist(); 1045 dict = plist_new_dict();
1050 xmlNode *dict = add_child_to_plist(plist, "dict", "\n", NULL, 0); 1046 plist_add_sub_key_el(dict, "Request");
1051 xmlNode *key; 1047 plist_add_sub_string_el(dict, "StartService");
1052 key = add_key_str_dict_element(plist, dict, "Request", "StartService", 1); 1048 plist_add_sub_key_el(dict, "Service");
1053 if (!key) { 1049 plist_add_sub_string_el(dict, service);
1054 xmlFreeDoc(plist);
1055 return IPHONE_E_UNKNOWN_ERROR;
1056 }
1057 key = add_key_str_dict_element(plist, dict, "Service", service, 1);
1058 if (!key) {
1059 xmlFreeDoc(plist);
1060 return IPHONE_E_UNKNOWN_ERROR;
1061 }
1062 1050
1063 xmlDocDumpMemory(plist, (xmlChar **) & XML_query, &length); 1051 /* send to iPhone */
1052 ret = iphone_lckd_send(client, dict);
1053 plist_free(dict);
1054 dict = NULL;
1064 1055
1065 ret = iphone_lckd_send(client, XML_query, length, &bytes);
1066 free(XML_query);
1067 if (IPHONE_E_SUCCESS != ret) 1056 if (IPHONE_E_SUCCESS != ret)
1068 return ret; 1057 return ret;
1069 1058
1070 ret = iphone_lckd_recv(client, &XML_query, &bytes); 1059 ret = iphone_lckd_recv(client, &dict);
1071 xmlFreeDoc(plist); 1060
1072 if (IPHONE_E_SUCCESS != ret) 1061 if (IPHONE_E_SUCCESS != ret)
1073 return ret; 1062 return ret;
1074 1063
1075 if (bytes <= 0) 1064 if (!dict)
1076 return IPHONE_E_NOT_ENOUGH_DATA; 1065 return IPHONE_E_PLIST_ERROR;
1077 else {
1078 plist = xmlReadMemory(XML_query, bytes, NULL, NULL, 0);
1079 if (!plist)
1080 return IPHONE_E_UNKNOWN_ERROR;
1081 dict = xmlDocGetRootElement(plist);
1082 if (!dict)
1083 return IPHONE_E_UNKNOWN_ERROR;
1084 for (dict = dict->children; dict; dict = dict->next) {
1085 if (!xmlStrcmp(dict->name, "dict"))
1086 break;
1087 }
1088 1066
1089 if (!dict) 1067 plist_t query_node = plist_find_node_by_string(dict, "StartService");
1090 return IPHONE_E_UNKNOWN_ERROR; 1068 plist_t result_key_node = plist_get_next_sibling(query_node);
1091 dictionary = read_dict_element_strings(dict); 1069 plist_t result_value_node = plist_get_next_sibling(result_key_node);
1092 1070
1093 for (i = 0; dictionary[i]; i += 2) { 1071 plist_t port_key_node = plist_find_node_by_key(dict, "Port");
1094 log_debug_msg("lockdownd_start_service() dictionary %s: %s\n", dictionary[i], dictionary[i + 1]); 1072 plist_t port_value_node = plist_get_next_sibling(port_key_node);
1095 1073
1096 if (!xmlStrcmp(dictionary[i], "Port")) { 1074 plist_type result_key_type = plist_get_node_type(result_key_node);
1097 port_loc = atoi(dictionary[i + 1]); 1075 plist_type result_value_type = plist_get_node_type(result_value_node);
1098 log_debug_msg("lockdownd_start_service() atoi'd port: %i\n", port); 1076 plist_type port_key_type = plist_get_node_type(port_key_node);
1099 } 1077 plist_type port_value_type = plist_get_node_type(port_value_node);
1100 1078
1101 if (!xmlStrcmp(dictionary[i], "Result")) { 1079 if (result_key_type == PLIST_KEY && result_value_type == PLIST_STRING && port_key_type == PLIST_KEY
1102 if (!xmlStrcmp(dictionary[i + 1], "Success")) { 1080 && port_value_type == PLIST_UINT) {
1103 result = 1;
1104 }
1105 }
1106 }
1107 1081
1108 log_debug_msg("lockdownd_start_service(): DATA RECEIVED:\n\n"); 1082 char *result_key = NULL;
1109 log_debug_msg(XML_query); 1083 char *result_value = NULL;
1110 log_debug_msg("end data received by lockdownd_start_service()\n"); 1084 char *port_key = NULL;
1085 uint64_t port_value = 0;
1111 1086
1112 free(XML_query); 1087 plist_get_key_val(result_key_node, &result_key);
1113 xmlFreeDoc(plist); 1088 plist_get_string_val(result_value_node, &result_value);
1114 free_dictionary(dictionary); 1089 plist_get_key_val(port_key_node, &port_key);
1115 if (port && result) { 1090 plist_get_uint_val(port_value_node, &port_value);
1091
1092 if (!strcmp(result_key, "Result") && !strcmp(result_value, "Success") && !strcmp(port_key, "Port")) {
1093 port_loc = port_value;
1094 ret = IPHONE_E_SUCCESS;
1095 }
1096
1097 if (port && ret == IPHONE_E_SUCCESS)
1116 *port = port_loc; 1098 *port = port_loc;
1117 return IPHONE_E_SUCCESS; 1099 else
1118 } else 1100 ret = IPHONE_E_UNKNOWN_ERROR;
1119 return IPHONE_E_UNKNOWN_ERROR;
1120 } 1101 }
1121 1102
1122 return IPHONE_E_UNKNOWN_ERROR; 1103 plist_free(dict);
1104 dict = NULL;
1105 return ret;
1123} 1106}