summaryrefslogtreecommitdiffstats
path: root/src/lockdown.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lockdown.c')
-rw-r--r--src/lockdown.c810
1 files changed, 417 insertions, 393 deletions
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