summaryrefslogtreecommitdiffstats
path: root/src/lockdown.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lockdown.c')
-rw-r--r--src/lockdown.c639
1 files changed, 320 insertions, 319 deletions
diff --git a/src/lockdown.c b/src/lockdown.c
index cf0d99e..c6d5f80 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
@@ -92,7 +65,6 @@ iphone_lckd_client_t new_lockdownd_client(iphone_device_t phone)
92 return control; 65 return control;
93} 66}
94 67
95
96/** Closes the lockdownd client and does the necessary housekeeping. 68/** Closes the lockdownd client and does the necessary housekeeping.
97 * 69 *
98 * @param control The lockdown client 70 * @param control The lockdown client
@@ -128,7 +100,7 @@ iphone_error_t iphone_lckd_recv(iphone_lckd_client_t client, char **dump_data, u
128 return IPHONE_E_INVALID_ARG; 100 return IPHONE_E_INVALID_ARG;
129 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; 101 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
130 char *receive; 102 char *receive;
131 uint32 datalen = 0, bytes = 0; 103 uint32_t datalen = 0, bytes = 0;
132 104
133 if (!client->in_SSL) 105 if (!client->in_SSL)
134 ret = iphone_mux_recv(client->connection, (char *) &datalen, sizeof(datalen), &bytes); 106 ret = iphone_mux_recv(client->connection, (char *) &datalen, sizeof(datalen), &bytes);
@@ -202,49 +174,55 @@ iphone_error_t lockdownd_hello(iphone_lckd_client_t control)
202{ 174{
203 if (!control) 175 if (!control)
204 return IPHONE_E_INVALID_ARG; 176 return IPHONE_E_INVALID_ARG;
205 xmlDocPtr plist = new_plist(); 177
206 xmlNode *dict, *key;
207 char **dictionary;
208 int bytes = 0, i = 0; 178 int bytes = 0, i = 0;
209 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; 179 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
210 180
181 plist_t dict = plist_new_dict();
182 plist_add_sub_element(dict, PLIST_KEY, (void *) "Request", strlen("Request"));
183 plist_add_sub_element(dict, PLIST_STRING, (void *) "QueryType", strlen("QueryType"));
184
211 log_debug_msg("lockdownd_hello() called\n"); 185 log_debug_msg("lockdownd_hello() called\n");
212 dict = add_child_to_plist(plist, "dict", "\n", NULL, 0); 186 char *XML_content = NULL;
213 key = add_key_str_dict_element(plist, dict, "Request", "QueryType", 1); 187 uint32_t length = 0;
214 char *XML_content;
215 uint32 length;
216 188
217 xmlDocDumpMemory(plist, (xmlChar **) & XML_content, &length); 189 plist_to_xml(dict, &XML_content, &length);
190 log_debug_msg("Send msg :\nsize : %i\nxml : %s", length, XML_content);
218 ret = iphone_lckd_send(control, XML_content, length, &bytes); 191 ret = iphone_lckd_send(control, XML_content, length, &bytes);
219 192
220 xmlFree(XML_content); 193 free(XML_content);
221 xmlFreeDoc(plist); 194 XML_content = NULL;
222 plist = NULL; 195 plist_free(dict);
196 dict = NULL;
197
223 ret = iphone_lckd_recv(control, &XML_content, &bytes); 198 ret = iphone_lckd_recv(control, &XML_content, &bytes);
199 log_debug_msg("Receive msg :\nsize : %i\nxml : %s", bytes, XML_content);
200 plist_from_xml(XML_content, bytes, &dict);
224 201
225 plist = xmlReadMemory(XML_content, bytes, NULL, NULL, 0);
226 if (!plist)
227 return IPHONE_E_PLIST_ERROR;
228 dict = xmlDocGetRootElement(plist);
229 for (dict = dict->children; dict; dict = dict->next) {
230 if (!xmlStrcmp(dict->name, "dict"))
231 break;
232 }
233 if (!dict) 202 if (!dict)
234 return IPHONE_E_DICT_ERROR; 203 return IPHONE_E_PLIST_ERROR;
235 dictionary = read_dict_element_strings(dict);
236 xmlFreeDoc(plist);
237 free(XML_content);
238 204
239 for (i = 0; dictionary[i]; i += 2) { 205 plist_t query_node = plist_find_node(dict, PLIST_STRING, "QueryType", strlen("QueryType"));
240 if (!strcmp(dictionary[i], "Result") && !strcmp(dictionary[i + 1], "Success")) { 206 plist_t result_node = plist_get_next_sibling(query_node);
241 log_debug_msg("lockdownd_hello(): success\n"); 207 plist_t value_node = plist_get_next_sibling(result_node);
242 ret = IPHONE_E_SUCCESS; 208
243 break; 209 plist_type result_type;
244 } 210 plist_type value_type;
211
212 char *result_value = NULL;
213 char *value_value = NULL;
214 uint64_t result_length = 0;
215 uint64_t value_length = 0;
216
217 plist_get_type_and_value(result_node, &result_type, (void *) (&result_value), &result_length);
218 plist_get_type_and_value(value_node, &value_type, (void *) (&value_value), &value_length);
219
220 if (result_type == PLIST_KEY &&
221 value_type == PLIST_STRING && !strcmp(result_value, "Result") && !strcmp(value_value, "Success")) {
222 log_debug_msg("lockdownd_hello(): success\n");
223 ret = IPHONE_E_SUCCESS;
245 } 224 }
246 225
247 free_dictionary(dictionary);
248 return ret; 226 return ret;
249} 227}
250 228
@@ -256,74 +234,94 @@ iphone_error_t lockdownd_hello(iphone_lckd_client_t control)
256 * 234 *
257 * @return IPHONE_E_SUCCESS on success. 235 * @return IPHONE_E_SUCCESS on success.
258 */ 236 */
259iphone_error_t lockdownd_generic_get_value(iphone_lckd_client_t control, const char *req_key, const char *req_string, 237iphone_error_t lockdownd_generic_get_value(iphone_lckd_client_t control, const char *req_key, char *req_string,
260 char **value) 238 gnutls_datum_t * value)
261{ 239{
262 if (!control || !req_key || !value || (value && *value)) 240 if (!control || !req_key || !value || value->data)
263 return IPHONE_E_INVALID_ARG; 241 return IPHONE_E_INVALID_ARG;
264 xmlDocPtr plist = new_plist(); 242
265 xmlNode *dict = NULL; 243 plist_t dict = NULL;
266 xmlNode *key = NULL;;
267 char **dictionary = NULL;
268 int bytes = 0, i = 0; 244 int bytes = 0, i = 0;
269 char *XML_content = NULL; 245 char *XML_content = NULL;
270 uint32 length = 0; 246 uint32_t length = 0;
271 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; 247 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
272 248
273 /* Setup DevicePublicKey request plist */ 249 /* Setup DevicePublicKey request plist */
274 dict = add_child_to_plist(plist, "dict", "\n", NULL, 0); 250 dict = plist_new_dict();
275 key = add_key_str_dict_element(plist, dict, req_key, req_string, 1); 251 plist_add_sub_element(dict, PLIST_KEY, (void *) req_key, strlen(req_key));
276 key = add_key_str_dict_element(plist, dict, "Request", "GetValue", 1); 252 plist_add_sub_element(dict, PLIST_STRING, (void *) req_string, strlen(req_string));
277 xmlDocDumpMemory(plist, (xmlChar **) & XML_content, &length); 253 plist_add_sub_element(dict, PLIST_KEY, (void *) "Request", strlen("Request"));
254 plist_add_sub_element(dict, PLIST_STRING, (void *) "GetValue", strlen("GetValue"));
255 plist_to_xml(dict, &XML_content, &length);
278 256
279 /* send to iPhone */ 257 /* send to iPhone */
258 log_debug_msg("Send msg :\nsize : %i\nxml : %s", length, XML_content);
280 ret = iphone_lckd_send(control, XML_content, length, &bytes); 259 ret = iphone_lckd_send(control, XML_content, length, &bytes);
281 260
282 xmlFree(XML_content); 261 free(XML_content);
283 xmlFreeDoc(plist); 262 XML_content = NULL;
284 plist = NULL; 263 plist_free(dict);
264 dict = NULL;
285 265
286 if (ret != IPHONE_E_SUCCESS) 266 if (ret != IPHONE_E_SUCCESS)
287 return ret; 267 return ret;
288 268
289 /* Now get iPhone's answer */ 269 /* Now get iPhone's answer */
290 ret = iphone_lckd_recv(control, &XML_content, &bytes); 270 ret = iphone_lckd_recv(control, &XML_content, &bytes);
271 log_debug_msg("Receive msg :\nsize : %i\nxml : %s", bytes, XML_content);
291 272
292 if (ret != IPHONE_E_SUCCESS) 273 if (ret != IPHONE_E_SUCCESS)
293 return ret; 274 return ret;
294 275
295 plist = xmlReadMemory(XML_content, bytes, NULL, NULL, 0); 276 plist_from_xml(XML_content, bytes, &dict);
296 if (!plist)
297 return IPHONE_E_PLIST_ERROR;
298 dict = xmlDocGetRootElement(plist);
299 for (dict = dict->children; dict; dict = dict->next) {
300 if (!xmlStrcmp(dict->name, "dict"))
301 break;
302 }
303 if (!dict) 277 if (!dict)
304 return IPHONE_E_DICT_ERROR; 278 return IPHONE_E_PLIST_ERROR;
305 279
306 /* Parse xml to check success and to find public key */ 280 plist_t query_node = plist_find_node(dict, PLIST_STRING, "GetValue", strlen("GetValue"));
307 dictionary = read_dict_element_strings(dict); 281 plist_t result_key_node = plist_get_next_sibling(query_node);
308 xmlFreeDoc(plist); 282 plist_t result_value_node = plist_get_next_sibling(result_key_node);
309 free(XML_content);
310 283
311 int success = 0; 284 plist_type result_key_type;
312 for (i = 0; dictionary[i]; i += 2) { 285 plist_type result_value_type;
313 if (!strcmp(dictionary[i], "Result") && !strcmp(dictionary[i + 1], "Success")) { 286 char *result_key = NULL;
314 success = 1; 287 char *result_value = NULL;
315 } 288 uint64_t result_length = 0;
316 if (!strcmp(dictionary[i], "Value")) { 289 uint64_t value_length = 0;
317 *value = strdup(dictionary[i + 1]); 290
318 } 291 plist_get_type_and_value(result_key_node, &result_key_type, (void *) (&result_key), &result_length);
292 plist_get_type_and_value(result_value_node, &result_value_type, (void *) (&result_value), &value_length);
293
294 if (result_key_type == PLIST_KEY &&
295 result_value_type == PLIST_STRING && !strcmp(result_key, "Result") && !strcmp(result_value, "Success")) {
296 log_debug_msg("lockdownd_generic_get_value(): success\n");
297 ret = IPHONE_E_SUCCESS;
319 } 298 }
320 299
321 if (dictionary) { 300 if (ret != IPHONE_E_SUCCESS) {
322 free_dictionary(dictionary); 301 return IPHONE_E_DICT_ERROR;
323 dictionary = NULL;
324 } 302 }
325 if (success) 303
304 plist_t value_key_node = plist_get_next_sibling(result_key_node);
305 plist_t value_value_node = plist_get_next_sibling(value_key_node);
306 plist_type value_key_type;
307 plist_type value_value_type;
308 char *value_key = NULL;
309 char *value_value = NULL;
310 uint64_t key_length = 0;
311 uint64_t valval_length = 0;
312
313 plist_get_type_and_value(value_key_node, &value_key_type, (void *) (&value_key), &key_length);
314 plist_get_type_and_value(value_value_node, &value_value_type, (void *) (&value_value), &valval_length);
315
316 if (value_key_type == PLIST_KEY && !strcmp(result_key, "Value")) {
317 log_debug_msg("lockdownd_generic_get_value(): success\n");
318 value->data = value_value;
319 value->size = valval_length;
326 ret = IPHONE_E_SUCCESS; 320 ret = IPHONE_E_SUCCESS;
321 }
322
323 plist_free(dict);
324 free(XML_content);
327 return ret; 325 return ret;
328} 326}
329 327
@@ -335,7 +333,9 @@ iphone_error_t lockdownd_generic_get_value(iphone_lckd_client_t control, const c
335 */ 333 */
336iphone_error_t lockdownd_get_device_uid(iphone_lckd_client_t control, char **uid) 334iphone_error_t lockdownd_get_device_uid(iphone_lckd_client_t control, char **uid)
337{ 335{
338 return lockdownd_generic_get_value(control, "Key", "UniqueDeviceID", uid); 336 gnutls_datum_t temp = { NULL, 0 };
337 return lockdownd_generic_get_value(control, "Key", "UniqueDeviceID", &temp);
338 *uid = temp.data;
339} 339}
340 340
341/** Askes for the device's public key. Part of the lockdownd handshake. 341/** Askes for the device's public key. Part of the lockdownd handshake.
@@ -344,7 +344,7 @@ iphone_error_t lockdownd_get_device_uid(iphone_lckd_client_t control, char **uid
344 * 344 *
345 * @return 1 on success and 0 on failure. 345 * @return 1 on success and 0 on failure.
346 */ 346 */
347iphone_error_t lockdownd_get_device_public_key(iphone_lckd_client_t control, char **public_key) 347iphone_error_t lockdownd_get_device_public_key(iphone_lckd_client_t control, gnutls_datum_t * public_key)
348{ 348{
349 return lockdownd_generic_get_value(control, "Key", "DevicePublicKey", public_key); 349 return lockdownd_generic_get_value(control, "Key", "DevicePublicKey", public_key);
350} 350}
@@ -416,51 +416,52 @@ iphone_error_t iphone_lckd_new_client(iphone_device_t device, iphone_lckd_client
416iphone_error_t lockdownd_pair_device(iphone_lckd_client_t control, char *uid, char *host_id) 416iphone_error_t lockdownd_pair_device(iphone_lckd_client_t control, char *uid, char *host_id)
417{ 417{
418 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; 418 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
419 xmlDocPtr plist = new_plist(); 419 plist_t dict = NULL;
420 xmlNode *dict = NULL; 420 plist_t dict_record = NULL;
421 xmlNode *dictRecord = NULL;
422 char **dictionary = NULL;
423 int bytes = 0, i = 0; 421 int bytes = 0, i = 0;
424 char *XML_content = NULL; 422 char *XML_content = NULL;
425 uint32 length = 0; 423 uint32_t length = 0;
426 424
427 char *device_cert_b64 = NULL; 425 gnutls_datum_t device_cert = { NULL, 0 };
428 char *host_cert_b64 = NULL; 426 gnutls_datum_t host_cert = { NULL, 0 };
429 char *root_cert_b64 = NULL; 427 gnutls_datum_t root_cert = { NULL, 0 };
430 char *public_key_b64 = NULL; 428 gnutls_datum_t public_key = { NULL, 0 };
431 429
432 ret = lockdownd_get_device_public_key(control, &public_key_b64); 430 ret = lockdownd_get_device_public_key(control, &public_key);
433 if (ret != IPHONE_E_SUCCESS) { 431 if (ret != IPHONE_E_SUCCESS) {
434 fprintf(stderr, "Device refused to send public key.\n"); 432 fprintf(stderr, "Device refused to send public key.\n");
435 return ret; 433 return ret;
436 } 434 }
437 435
438 ret = lockdownd_gen_pair_cert(public_key_b64, &device_cert_b64, &host_cert_b64, &root_cert_b64); 436 ret = lockdownd_gen_pair_cert(public_key, &device_cert, &host_cert, &root_cert);
439 if (ret != IPHONE_E_SUCCESS) { 437 if (ret != IPHONE_E_SUCCESS) {
440 free(public_key_b64); 438 free(public_key.data);
441 return ret; 439 return ret;
442 } 440 }
443 441
444 /* Setup Pair request plist */ 442 /* Setup Pair request plist */
445 dict = add_child_to_plist(plist, "dict", "\n", NULL, 0); 443 dict = plist_new_dict();
446 dictRecord = add_key_dict_node(plist, dict, "PairRecord", "\n", 1); 444 plist_add_sub_element(dict, PLIST_KEY, (void *) "PairRecord", strlen("PairRecord"));
447 //dictRecord = add_child_to_plist(plist, "dict", "\n", NULL, 1); 445 dict_record = plist_add_sub_element(dict, PLIST_DICT, NULL, 0);
448 add_key_data_dict_element(plist, dictRecord, "DeviceCertificate", device_cert_b64, 2); 446 plist_add_sub_element(dict_record, PLIST_KEY, (void *) "DeviceCertificate", strlen("DeviceCertificate"));
449 add_key_data_dict_element(plist, dictRecord, "HostCertificate", host_cert_b64, 2); 447 plist_add_sub_element(dict_record, PLIST_DATA, (void *) device_cert.data, device_cert.size);
450 add_key_str_dict_element(plist, dictRecord, "HostID", host_id, 2); 448 plist_add_sub_element(dict_record, PLIST_KEY, (void *) "HostCertificate", strlen("HostCertificate"));
451 add_key_data_dict_element(plist, dictRecord, "RootCertificate", root_cert_b64, 2); 449 plist_add_sub_element(dict_record, PLIST_DATA, (void *) host_cert.data, host_cert.size);
452 add_key_str_dict_element(plist, dict, "Request", "Pair", 1); 450 plist_add_sub_element(dict_record, PLIST_KEY, (void *) "HostID", strlen("HostID"));
453 451 plist_add_sub_element(dict_record, PLIST_STRING, (void *) host_id, strlen(host_id));
454 xmlDocDumpMemory(plist, (xmlChar **) & XML_content, &length); 452 plist_add_sub_element(dict_record, PLIST_KEY, (void *) "RootCertificate", strlen("RootCertificate"));
455 453 plist_add_sub_element(dict_record, PLIST_DATA, (void *) root_cert.data, root_cert.size);
456 printf("XML Pairing request : %s\n", XML_content); 454 plist_add_sub_element(dict_record, PLIST_KEY, (void *) "Request", strlen("Request"));
455 plist_add_sub_element(dict_record, PLIST_STRING, (void *) "Pair", strlen("Pair"));
456 plist_to_xml(dict, &XML_content, &length);
457 log_debug_msg("XML Pairing request :\nsize : %i\nxml :\n %s", length, XML_content);
457 458
458 /* send to iPhone */ 459 /* send to iPhone */
459 ret = iphone_lckd_send(control, XML_content, length, &bytes); 460 ret = iphone_lckd_send(control, XML_content, length, &bytes);
460 461
461 xmlFree(XML_content); 462 free(XML_content);
462 xmlFreeDoc(plist); 463 plist_free(dict);
463 plist = NULL; 464 dict = NULL;
464 465
465 if (ret != IPHONE_E_SUCCESS) 466 if (ret != IPHONE_E_SUCCESS)
466 return ret; 467 return ret;
@@ -475,48 +476,39 @@ iphone_error_t lockdownd_pair_device(iphone_lckd_client_t control, char *uid, ch
475 log_debug_msg(XML_content); 476 log_debug_msg(XML_content);
476 log_debug_msg("\n\n"); 477 log_debug_msg("\n\n");
477 478
478 plist = xmlReadMemory(XML_content, bytes, NULL, NULL, 0); 479 plist_from_xml(XML_content, bytes, &dict);
479 if (!plist) { 480 if (!dict)
480 free(public_key_b64);
481 return IPHONE_E_PLIST_ERROR; 481 return IPHONE_E_PLIST_ERROR;
482 }
483 dict = xmlDocGetRootElement(plist);
484 for (dict = dict->children; dict; dict = dict->next) {
485 if (!xmlStrcmp(dict->name, "dict"))
486 break;
487 }
488 if (!dict) {
489 free(public_key_b64);
490 return IPHONE_E_DICT_ERROR;
491 }
492 482
493 /* Parse xml to check success and to find public key */ 483 plist_t query_node = plist_find_node(dict, PLIST_STRING, "Pair", strlen("Pair"));
494 dictionary = read_dict_element_strings(dict); 484 plist_t result_key_node = plist_get_next_sibling(query_node);
495 xmlFreeDoc(plist); 485 plist_t result_value_node = plist_get_next_sibling(result_key_node);
496 free(XML_content);
497 486
498 int success = 0; 487 plist_type result_key_type;
499 for (i = 0; dictionary[i]; i += 2) { 488 plist_type result_value_type;
500 if (!strcmp(dictionary[i], "Result") && !strcmp(dictionary[i + 1], "Success")) { 489 char *result_key = NULL;
501 success = 1; 490 char *result_value = NULL;
502 } 491 uint64_t key_length = 0;
503 } 492 uint64_t val_length = 0;
493
494 plist_get_type_and_value(result_key_node, &result_key_type, (void *) (&result_key), &key_length);
495 plist_get_type_and_value(result_value_node, &result_value_type, (void *) (&result_value), &val_length);
504 496
505 if (dictionary) { 497 if (result_key_type == PLIST_KEY &&
506 free_dictionary(dictionary); 498 result_value_type == PLIST_STRING && !strcmp(result_key, "Result") && !strcmp(result_value, "Success")) {
507 dictionary = NULL; 499 ret = IPHONE_E_SUCCESS;
508 } 500 }
509 501
510 /* store public key in config if pairing succeeded */ 502 /* store public key in config if pairing succeeded */
511 if (success) { 503 if (ret == IPHONE_E_SUCCESS) {
512 log_debug_msg("lockdownd_pair_device: pair success\n"); 504 log_debug_msg("lockdownd_pair_device: pair success\n");
513 store_device_public_key(uid, public_key_b64); 505 store_device_public_key(uid, public_key);
514 ret = IPHONE_E_SUCCESS; 506 ret = IPHONE_E_SUCCESS;
515 } else { 507 } else {
516 log_debug_msg("lockdownd_pair_device: pair failure\n"); 508 log_debug_msg("lockdownd_pair_device: pair failure\n");
517 ret = IPHONE_E_PAIRING_FAILED; 509 ret = IPHONE_E_PAIRING_FAILED;
518 } 510 }
519 free(public_key_b64); 511 free(public_key.data);
520 return ret; 512 return ret;
521} 513}
522 514
@@ -525,25 +517,19 @@ iphone_error_t lockdownd_pair_device(iphone_lckd_client_t control, char *uid, ch
525 * 517 *
526 * @return IPHONE_E_SUCCESS on success. 518 * @return IPHONE_E_SUCCESS on success.
527 */ 519 */
528iphone_error_t lockdownd_gen_pair_cert(char *public_key_b64, char **device_cert_b64, char **host_cert_b64, 520iphone_error_t lockdownd_gen_pair_cert(gnutls_datum_t public_key, gnutls_datum_t * odevice_cert,
529 char **root_cert_b64) 521 gnutls_datum_t * ohost_cert, gnutls_datum_t * oroot_cert)
530{ 522{
531 if (!public_key_b64 || !device_cert_b64 || !host_cert_b64 || !root_cert_b64) 523 if (!public_key.data || !odevice_cert || !ohost_cert || !oroot_cert)
532 return IPHONE_E_INVALID_ARG; 524 return IPHONE_E_INVALID_ARG;
533 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; 525 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
534 526
535 gnutls_datum_t modulus = { NULL, 0 }; 527 gnutls_datum_t modulus = { NULL, 0 };
536 gnutls_datum_t exponent = { NULL, 0 }; 528 gnutls_datum_t exponent = { NULL, 0 };
537 529
538 /* first decode base64 public_key */
539 gnutls_datum_t pem_pub_key;
540 gsize decoded_size;
541 pem_pub_key.data = g_base64_decode(public_key_b64, &decoded_size);
542 pem_pub_key.size = decoded_size;
543
544 /* now decode the PEM encoded key */ 530 /* now decode the PEM encoded key */
545 gnutls_datum_t der_pub_key; 531 gnutls_datum_t der_pub_key;
546 if (GNUTLS_E_SUCCESS == gnutls_pem_base64_decode_alloc("RSA PUBLIC KEY", &pem_pub_key, &der_pub_key)) { 532 if (GNUTLS_E_SUCCESS == gnutls_pem_base64_decode_alloc("RSA PUBLIC KEY", &public_key, &der_pub_key)) {
547 533
548 /* initalize asn.1 parser */ 534 /* initalize asn.1 parser */
549 ASN1_TYPE pkcs1 = ASN1_TYPE_EMPTY; 535 ASN1_TYPE pkcs1 = ASN1_TYPE_EMPTY;
@@ -627,10 +613,18 @@ iphone_error_t lockdownd_gen_pair_cert(char *public_key_b64, char **device_cert_
627 dev_pem.data = gnutls_malloc(dev_pem.size); 613 dev_pem.data = gnutls_malloc(dev_pem.size);
628 gnutls_x509_crt_export(dev_cert, GNUTLS_X509_FMT_PEM, dev_pem.data, &dev_pem.size); 614 gnutls_x509_crt_export(dev_cert, GNUTLS_X509_FMT_PEM, dev_pem.data, &dev_pem.size);
629 615
630 /* now encode certificates for output */ 616 /* copy buffer for output */
631 *device_cert_b64 = g_base64_encode(dev_pem.data, dev_pem.size); 617 odevice_cert->data = malloc(dev_pem.size);
632 *host_cert_b64 = g_base64_encode(pem_host_cert.data, pem_host_cert.size); 618 memcpy(odevice_cert->data, dev_pem.data, dev_pem.size);
633 *root_cert_b64 = g_base64_encode(pem_root_cert.data, pem_root_cert.size); 619 odevice_cert->size = dev_pem.size;
620
621 ohost_cert->data = malloc(pem_host_cert.size);
622 memcpy(ohost_cert->data, pem_host_cert.data, pem_host_cert.size);
623 ohost_cert->size = pem_host_cert.size;
624
625 oroot_cert->data = malloc(pem_root_cert.size);
626 memcpy(oroot_cert->data, pem_root_cert.data, pem_root_cert.size);
627 oroot_cert->size = pem_root_cert.size;
634 } 628 }
635 gnutls_free(pem_root_priv.data); 629 gnutls_free(pem_root_priv.data);
636 gnutls_free(pem_root_cert.data); 630 gnutls_free(pem_root_cert.data);
@@ -642,7 +636,6 @@ iphone_error_t lockdownd_gen_pair_cert(char *public_key_b64, char **device_cert_
642 gnutls_free(exponent.data); 636 gnutls_free(exponent.data);
643 637
644 gnutls_free(der_pub_key.data); 638 gnutls_free(der_pub_key.data);
645 g_free(pem_pub_key.data);
646 639
647 return ret; 640 return ret;
648} 641}
@@ -656,113 +649,112 @@ iphone_error_t lockdownd_gen_pair_cert(char *public_key_b64, char **device_cert_
656 */ 649 */
657iphone_error_t lockdownd_start_SSL_session(iphone_lckd_client_t control, const char *HostID) 650iphone_error_t lockdownd_start_SSL_session(iphone_lckd_client_t control, const char *HostID)
658{ 651{
659 xmlDocPtr plist = new_plist(); 652 plist_t dict = NULL;
660 xmlNode *dict = add_child_to_plist(plist, "dict", "\n", NULL, 0); 653 char *XML_content = NULL;
661 xmlNode *key; 654 uint32_t length = 0, bytes = 0, return_me = 0;
662 char *what2send = NULL, **dictionary = NULL; 655
663 uint32 len = 0, bytes = 0, return_me = 0, i = 0;
664 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; 656 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
665 // end variables
666 657
667 key = add_key_str_dict_element(plist, dict, "HostID", HostID, 1); 658 /* Setup DevicePublicKey request plist */
668 if (!key) { 659 dict = plist_new_dict();
669 log_debug_msg("Couldn't add a key.\n"); 660 plist_add_sub_element(dict, PLIST_KEY, (void *) "HostID", strlen("HostID"));
670 xmlFreeDoc(plist); 661 plist_add_sub_element(dict, PLIST_STRING, (void *) HostID, strlen(HostID));
671 return IPHONE_E_DICT_ERROR; 662 plist_add_sub_element(dict, PLIST_KEY, (void *) "Request", strlen("Request"));
672 } 663 plist_add_sub_element(dict, PLIST_STRING, (void *) "StartSession", strlen("StartSession"));
673 key = add_key_str_dict_element(plist, dict, "Request", "StartSession", 1); 664 plist_to_xml(dict, &XML_content, &length);
674 if (!key) { 665 log_debug_msg("Send msg :\nsize : %i\nxml : %s", length, XML_content);
675 log_debug_msg("Couldn't add a key.\n");
676 xmlFreeDoc(plist);
677 return IPHONE_E_DICT_ERROR;
678 }
679 666
680 xmlDocDumpMemory(plist, (xmlChar **) & what2send, &len); 667 ret = iphone_lckd_send(control, XML_content, length, &bytes);
681 ret = iphone_lckd_send(control, what2send, len, &bytes);
682 668
683 xmlFree(what2send); 669 free(XML_content);
684 xmlFreeDoc(plist); 670 XML_content = NULL;
671 plist_free(dict);
672 dict = NULL;
685 673
686 if (ret != IPHONE_E_SUCCESS) 674 if (ret != IPHONE_E_SUCCESS)
687 return ret; 675 return ret;
688 676
689 if (bytes > 0) { 677 if (bytes > 0) {
690 ret = iphone_lckd_recv(control, &what2send, &len); 678 ret = iphone_lckd_recv(control, &XML_content, &bytes);
691 plist = xmlReadMemory(what2send, len, NULL, NULL, 0); 679 log_debug_msg("Receive msg :\nsize : %i\nxml : %s", bytes, XML_content);
692 dict = xmlDocGetRootElement(plist); 680 plist_from_xml(XML_content, bytes, &dict);
693 if (!dict) 681 if (!dict)
694 return IPHONE_E_DICT_ERROR; 682 return IPHONE_E_PLIST_ERROR;
695 for (dict = dict->children; dict; dict = dict->next) { 683
696 if (!xmlStrcmp(dict->name, "dict")) 684 plist_t query_node = plist_find_node(dict, PLIST_STRING, "StartSession", strlen("StartSession"));
697 break; 685 plist_t result_key_node = plist_get_next_sibling(query_node);
698 } 686 plist_t result_value_node = plist_get_next_sibling(result_key_node);
699 dictionary = read_dict_element_strings(dict); 687
700 xmlFreeDoc(plist); 688 plist_type result_key_type;
701 free(what2send); 689 plist_type result_value_type;
702 for (i = 0; dictionary[i]; i += 2) { 690 char *result_key = NULL;
703 if (!strcmp(dictionary[i], "Result") && !strcmp(dictionary[i + 1], "Success")) { 691 char *result_value = NULL;
704 // Set up GnuTLS... 692 uint64_t key_length = 0;
705 //gnutls_anon_client_credentials_t anoncred; 693 uint64_t val_length = 0;
706 gnutls_certificate_credentials_t xcred; 694
707 695 plist_get_type_and_value(result_key_node, &result_key_type, (void *) (&result_key), &key_length);
708 log_debug_msg("We started the session OK, now trying GnuTLS\n"); 696 plist_get_type_and_value(result_value_node, &result_value_type, (void *) (&result_value), &val_length);
709 errno = 0; 697
710 gnutls_global_init(); 698 free(XML_content);
711 //gnutls_anon_allocate_client_credentials(&anoncred); 699 XML_content = NULL;
712 gnutls_certificate_allocate_credentials(&xcred); 700 plist_free(dict);
713 gnutls_certificate_set_x509_trust_file(xcred, "hostcert.pem", GNUTLS_X509_FMT_PEM); 701 dict = NULL;
714 gnutls_init(control->ssl_session, GNUTLS_CLIENT); 702
715 { 703 if (result_key_type == PLIST_KEY &&
716 int protocol_priority[16] = { GNUTLS_SSL3, 0 }; 704 result_value_type == PLIST_STRING && !strcmp(result_key, "Result") && !strcmp(result_value, "Success")) {
717 int kx_priority[16] = { GNUTLS_KX_ANON_DH, GNUTLS_KX_RSA, 0 }; 705 // Set up GnuTLS...
718 int cipher_priority[16] = { GNUTLS_CIPHER_AES_128_CBC, GNUTLS_CIPHER_AES_256_CBC, 0 }; 706 //gnutls_anon_client_credentials_t anoncred;
719 int mac_priority[16] = { GNUTLS_MAC_SHA1, GNUTLS_MAC_MD5, 0 }; 707 gnutls_certificate_credentials_t xcred;
720 int comp_priority[16] = { GNUTLS_COMP_NULL, 0 }; 708
721 709 log_debug_msg("We started the session OK, now trying GnuTLS\n");
722 gnutls_cipher_set_priority(*control->ssl_session, cipher_priority); 710 errno = 0;
723 gnutls_compression_set_priority(*control->ssl_session, comp_priority); 711 gnutls_global_init();
724 gnutls_kx_set_priority(*control->ssl_session, kx_priority); 712 //gnutls_anon_allocate_client_credentials(&anoncred);
725 gnutls_protocol_set_priority(*control->ssl_session, protocol_priority); 713 gnutls_certificate_allocate_credentials(&xcred);
726 gnutls_mac_set_priority(*control->ssl_session, mac_priority); 714 gnutls_certificate_set_x509_trust_file(xcred, "hostcert.pem", GNUTLS_X509_FMT_PEM);
727 715 gnutls_init(control->ssl_session, GNUTLS_CLIENT);
728 } 716 {
729 gnutls_credentials_set(*control->ssl_session, GNUTLS_CRD_CERTIFICATE, xcred); // this part is killing me. 717 int protocol_priority[16] = { GNUTLS_SSL3, 0 };
730 718 int kx_priority[16] = { GNUTLS_KX_ANON_DH, GNUTLS_KX_RSA, 0 };
731 log_debug_msg("GnuTLS step 1...\n"); 719 int cipher_priority[16] = { GNUTLS_CIPHER_AES_128_CBC, GNUTLS_CIPHER_AES_256_CBC, 0 };
732 gnutls_transport_set_ptr(*control->ssl_session, (gnutls_transport_ptr_t) control); 720 int mac_priority[16] = { GNUTLS_MAC_SHA1, GNUTLS_MAC_MD5, 0 };
733 log_debug_msg("GnuTLS step 2...\n"); 721 int comp_priority[16] = { GNUTLS_COMP_NULL, 0 };
734 gnutls_transport_set_push_function(*control->ssl_session, (gnutls_push_func) & lockdownd_secuwrite); 722
735 log_debug_msg("GnuTLS step 3...\n"); 723 gnutls_cipher_set_priority(*control->ssl_session, cipher_priority);
736 gnutls_transport_set_pull_function(*control->ssl_session, (gnutls_pull_func) & lockdownd_securead); 724 gnutls_compression_set_priority(*control->ssl_session, comp_priority);
737 log_debug_msg("GnuTLS step 4 -- now handshaking...\n"); 725 gnutls_kx_set_priority(*control->ssl_session, kx_priority);
738 726 gnutls_protocol_set_priority(*control->ssl_session, protocol_priority);
739 if (errno) 727 gnutls_mac_set_priority(*control->ssl_session, mac_priority);
740 log_debug_msg("WARN: errno says %s before handshake!\n", strerror(errno)); 728
741 return_me = gnutls_handshake(*control->ssl_session); 729 }
742 log_debug_msg("GnuTLS handshake done...\n"); 730 gnutls_credentials_set(*control->ssl_session, GNUTLS_CRD_CERTIFICATE, xcred); // this part is killing me.
743 731
744 free_dictionary(dictionary); 732 log_debug_msg("GnuTLS step 1...\n");
745 733 gnutls_transport_set_ptr(*control->ssl_session, (gnutls_transport_ptr_t) control);
746 if (return_me != GNUTLS_E_SUCCESS) { 734 log_debug_msg("GnuTLS step 2...\n");
747 log_debug_msg("GnuTLS reported something wrong.\n"); 735 gnutls_transport_set_push_function(*control->ssl_session, (gnutls_push_func) & lockdownd_secuwrite);
748 gnutls_perror(return_me); 736 log_debug_msg("GnuTLS step 3...\n");
749 log_debug_msg("oh.. errno says %s\n", strerror(errno)); 737 gnutls_transport_set_pull_function(*control->ssl_session, (gnutls_pull_func) & lockdownd_securead);
750 return IPHONE_E_SSL_ERROR; 738 log_debug_msg("GnuTLS step 4 -- now handshaking...\n");
751 } else { 739
752 control->in_SSL = 1; 740 if (errno)
753 return IPHONE_E_SUCCESS; 741 log_debug_msg("WARN: errno says %s before handshake!\n", strerror(errno));
754 } 742 return_me = gnutls_handshake(*control->ssl_session);
743 log_debug_msg("GnuTLS handshake done...\n");
744
745 if (return_me != GNUTLS_E_SUCCESS) {
746 log_debug_msg("GnuTLS reported something wrong.\n");
747 gnutls_perror(return_me);
748 log_debug_msg("oh.. errno says %s\n", strerror(errno));
749 return IPHONE_E_SSL_ERROR;
750 } else {
751 control->in_SSL = 1;
752 return IPHONE_E_SUCCESS;
755 } 753 }
756 } 754 }
757 755
758 log_debug_msg("Apparently failed negotiating with lockdownd.\n"); 756 log_debug_msg("Apparently failed negotiating with lockdownd.\n");
759 log_debug_msg("Responding dictionary: \n"); 757 log_debug_msg("Responding dictionary: \n");
760 for (i = 0; dictionary[i]; i += 2) {
761 log_debug_msg("\t%s: %s\n", dictionary[i], dictionary[i + 1]);
762 }
763
764
765 free_dictionary(dictionary);
766 return IPHONE_E_SSL_ERROR; 758 return IPHONE_E_SSL_ERROR;
767 } else { 759 } else {
768 log_debug_msg("Didn't get enough bytes.\n"); 760 log_debug_msg("Didn't get enough bytes.\n");
@@ -894,81 +886,90 @@ iphone_error_t iphone_lckd_start_service(iphone_lckd_client_t client, const char
894 if (!client->in_SSL && !lockdownd_start_SSL_session(client, host_id)) 886 if (!client->in_SSL && !lockdownd_start_SSL_session(client, host_id))
895 return IPHONE_E_SSL_ERROR; 887 return IPHONE_E_SSL_ERROR;
896 888
897 char *XML_query, **dictionary; 889
898 uint32 length, i = 0, port_loc = 0, bytes = 0; 890 plist_t dict = NULL;
899 uint8 result = 0; 891 char *XML_content = NULL;
892 uint32_t length, i = 0, port_loc = 0, bytes = 0;
900 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; 893 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
901 894
902 free(host_id); 895 free(host_id);
903 host_id = NULL; 896 host_id = NULL;
904 897
905 xmlDocPtr plist = new_plist(); 898 dict = plist_new_dict();
906 xmlNode *dict = add_child_to_plist(plist, "dict", "\n", NULL, 0); 899 plist_add_sub_element(dict, PLIST_KEY, (void *) "Request", strlen("Request"));
907 xmlNode *key; 900 plist_add_sub_element(dict, PLIST_STRING, (void *) "StartService", strlen("StartService"));
908 key = add_key_str_dict_element(plist, dict, "Request", "StartService", 1); 901 plist_add_sub_element(dict, PLIST_KEY, (void *) "Service", strlen("Service"));
909 if (!key) { 902 plist_add_sub_element(dict, PLIST_STRING, (void *) service, strlen(service));
910 xmlFreeDoc(plist); 903 plist_to_xml(dict, &XML_content, &length);
911 return IPHONE_E_UNKNOWN_ERROR;
912 }
913 key = add_key_str_dict_element(plist, dict, "Service", service, 1);
914 if (!key) {
915 xmlFreeDoc(plist);
916 return IPHONE_E_UNKNOWN_ERROR;
917 }
918 904
919 xmlDocDumpMemory(plist, (xmlChar **) & XML_query, &length); 905 /* send to iPhone */
906 log_debug_msg("Send msg :\nsize : %i\nxml : %s", length, XML_content);
907 ret = iphone_lckd_send(client, XML_content, length, &bytes);
908
909 free(XML_content);
910 XML_content = NULL;
911 plist_free(dict);
912 dict = NULL;
920 913
921 ret = iphone_lckd_send(client, XML_query, length, &bytes);
922 free(XML_query);
923 if (IPHONE_E_SUCCESS != ret) 914 if (IPHONE_E_SUCCESS != ret)
924 return ret; 915 return ret;
925 916
926 ret = iphone_lckd_recv(client, &XML_query, &bytes); 917 ret = iphone_lckd_recv(client, &XML_content, &bytes);
927 xmlFreeDoc(plist); 918
928 if (IPHONE_E_SUCCESS != ret) 919 if (IPHONE_E_SUCCESS != ret)
929 return ret; 920 return ret;
930 921
922 plist_from_xml(XML_content, bytes, &dict);
923 if (!dict)
924 return IPHONE_E_PLIST_ERROR;
925
926
931 if (bytes <= 0) 927 if (bytes <= 0)
932 return IPHONE_E_NOT_ENOUGH_DATA; 928 return IPHONE_E_NOT_ENOUGH_DATA;
933 else { 929 else {
934 plist = xmlReadMemory(XML_query, bytes, NULL, NULL, 0);
935 if (!plist)
936 return IPHONE_E_UNKNOWN_ERROR;
937 dict = xmlDocGetRootElement(plist);
938 if (!dict)
939 return IPHONE_E_UNKNOWN_ERROR;
940 for (dict = dict->children; dict; dict = dict->next) {
941 if (!xmlStrcmp(dict->name, "dict"))
942 break;
943 }
944 930
945 if (!dict) 931 plist_t query_node = plist_find_node(dict, PLIST_STRING, "StartService", strlen("StartService"));
946 return IPHONE_E_UNKNOWN_ERROR; 932 plist_t result_key_node = plist_get_next_sibling(query_node);
947 dictionary = read_dict_element_strings(dict); 933 plist_t result_value_node = plist_get_next_sibling(result_key_node);
948 934
949 for (i = 0; dictionary[i]; i += 2) { 935 plist_t port_key_node = plist_find_node(dict, PLIST_KEY, "Port", strlen("Port"));
950 log_debug_msg("lockdownd_start_service() dictionary %s: %s\n", dictionary[i], dictionary[i + 1]); 936 plist_t port_value_node = plist_get_next_sibling(port_key_node);
951 937
952 if (!xmlStrcmp(dictionary[i], "Port")) { 938 plist_type result_key_type;
953 port_loc = atoi(dictionary[i + 1]); 939 plist_type result_value_type;
954 log_debug_msg("lockdownd_start_service() atoi'd port: %i\n", port); 940 plist_type port_key_type;
955 } 941 plist_type port_value_type;
956 942 char *result_key = NULL;
957 if (!xmlStrcmp(dictionary[i], "Result")) { 943 char *result_value = NULL;
958 if (!xmlStrcmp(dictionary[i + 1], "Success")) { 944 char *port_key = NULL;
959 result = 1; 945 uint64_t res_key_length = 0;
960 } 946 uint64_t res_val_length = 0;
961 } 947 uint64_t port_key_length = 0;
948 uint64_t port_val_length = 0;
949 uint64_t port_value = 0;
950
951 plist_get_type_and_value(result_key_node, &result_key_type, (void *) (&result_key), &res_key_length);
952 plist_get_type_and_value(result_value_node, &result_value_type, (void *) (&result_value), &res_val_length);
953 plist_get_type_and_value(port_key_node, &port_key_type, (void *) (&port_key), &port_key_length);
954 plist_get_type_and_value(port_value_node, &port_value_type, (void *) (&port_value), &port_val_length);
955
956 if (result_key_type == PLIST_KEY &&
957 result_value_type == PLIST_STRING &&
958 port_key_type == PLIST_KEY &&
959 port_value_type == PLIST_UINT &&
960 !strcmp(result_key, "Result") && !strcmp(result_value, "Success") && !strcmp(port_key, "Port")) {
961 port_loc = port_value;
962 ret = IPHONE_E_SUCCESS;
962 } 963 }
963 964
964 log_debug_msg("lockdownd_start_service(): DATA RECEIVED:\n\n"); 965 log_debug_msg("lockdownd_start_service(): DATA RECEIVED:\n\n");
965 log_debug_msg(XML_query); 966 log_debug_msg(XML_content);
966 log_debug_msg("end data received by lockdownd_start_service()\n"); 967 log_debug_msg("end data received by lockdownd_start_service()\n");
967 968
968 free(XML_query); 969 free(XML_content);
969 xmlFreeDoc(plist); 970 plist_free(dict);
970 free_dictionary(dictionary); 971 dict = NULL;
971 if (port && result) { 972 if (port && ret == IPHONE_E_SUCCESS) {
972 *port = port_loc; 973 *port = port_loc;
973 return IPHONE_E_SUCCESS; 974 return IPHONE_E_SUCCESS;
974 } else 975 } else