summaryrefslogtreecommitdiffstats
path: root/src/lockdown.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lockdown.c')
-rw-r--r--src/lockdown.c778
1 files changed, 361 insertions, 417 deletions
diff --git a/src/lockdown.c b/src/lockdown.c
index a950ceb..7e1f1a8 100644
--- a/src/lockdown.c
+++ b/src/lockdown.c
@@ -33,6 +33,8 @@
33 33
34#include <plist/plist.h> 34#include <plist/plist.h>
35 35
36#define RESULT_SUCCESS 0
37#define RESULT_FAILURE 1
36 38
37const ASN1_ARRAY_TYPE pkcs1_asn1_tab[] = { 39const ASN1_ARRAY_TYPE pkcs1_asn1_tab[] = {
38 {"PKCS1", 536872976, 0}, 40 {"PKCS1", 536872976, 0},
@@ -43,28 +45,80 @@ const ASN1_ARRAY_TYPE pkcs1_asn1_tab[] = {
43 {0, 0, 0} 45 {0, 0, 0}
44}; 46};
45 47
46/** Creates a lockdownd client for the give iPhone. 48/**
49 * Internally used function for checking the result from lockdown's answer
50 * plist to a previously sent request.
47 * 51 *
48 * @param phone The iPhone to create a lockdownd client for 52 * @param dict The plist to evaluate.
53 * @param query_match Name of the request to match.
49 * 54 *
50 * @return The lockdownd client. 55 * @return RESULT_SUCCESS when the result is 'Success',
56 * RESULT_FAILURE when the result is 'Failure',
57 * or a negative value if an error occured during evaluation.
51 */ 58 */
52iphone_lckd_client_t new_lockdownd_client(iphone_device_t phone) 59static int lockdown_check_result(plist_t dict, const char *query_match)
53{ 60{
54 if (!phone) 61 int ret = -1;
55 return NULL;
56 62
57 int sfd = usbmuxd_connect(phone->handle, 0xf27e); 63 plist_t query_key = plist_find_node_by_key(dict, "Request");
58 if (sfd < 0) { 64 if (!query_key) {
59 log_debug_msg("%s: could not connect to lockdownd (device handle %d)\n", __func__, phone->handle); 65 return ret;
60 return NULL; 66 }
67 plist_t query_node = plist_get_next_sibling(query_key);
68 if (!query_node) {
69 return ret;
70 }
71 if (plist_get_node_type(query_node) != PLIST_STRING) {
72 return ret;
73 } else {
74 char *query_value = NULL;
75 plist_get_string_val(query_node, &query_value);
76 if (!query_value) {
77 return ret;
78 }
79 if (strcmp(query_value, query_match) != 0) {
80 free(query_value);
81 return ret;
82 }
83 free(query_value);
84 }
85
86 plist_t result_node = plist_get_next_sibling(query_node);
87 if (!result_node) {
88 return ret;
61 } 89 }
62 90
63 iphone_lckd_client_t control = (iphone_lckd_client_t) malloc(sizeof(struct iphone_lckd_client_int)); 91 plist_t value_node = plist_get_next_sibling(result_node);
64 control->sfd = sfd; 92 if (!value_node) {
65 control->ssl_session = (gnutls_session_t *) malloc(sizeof(gnutls_session_t)); 93 return ret;
66 control->in_SSL = 0; 94 }
67 return control; 95
96 plist_type result_type = plist_get_node_type(result_node);
97 plist_type value_type = plist_get_node_type(value_node);
98
99 if (result_type == PLIST_KEY && value_type == PLIST_STRING) {
100
101 char *result_value = NULL;
102 char *value_value = NULL;
103
104 plist_get_key_val(result_node, &result_value);
105 plist_get_string_val(value_node, &value_value);
106
107 if (result_value && value_value && !strcmp(result_value, "Result")) {
108 if (!strcmp(value_value, "Success")) {
109 ret = RESULT_SUCCESS;
110 } else if (!strcmp(value_value, "Failure")) {
111 ret = RESULT_FAILURE;
112 } else {
113 log_dbg_msg(DBGMASK_LOCKDOWND, "%s: ERROR: unknown result value '%s'\n", __func__, value_value);
114 }
115 }
116 if (result_value)
117 free(result_value);
118 if (value_value)
119 free(value_value);
120 }
121 return ret;
68} 122}
69 123
70/** 124/**
@@ -73,10 +127,10 @@ iphone_lckd_client_t new_lockdownd_client(iphone_device_t phone)
73 * 127 *
74 * @param control The lockdown client 128 * @param control The lockdown client
75 */ 129 */
76static void iphone_lckd_stop_session(iphone_lckd_client_t control) 130iphone_error_t lockdownd_stop_session(lockdownd_client_t client)
77{ 131{
78 if (!control) 132 if (!client)
79 return; //IPHONE_E_INVALID_ARG; 133 return IPHONE_E_INVALID_ARG;
80 134
81 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; 135 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
82 136
@@ -84,48 +138,31 @@ static void iphone_lckd_stop_session(iphone_lckd_client_t control)
84 plist_add_sub_key_el(dict, "Request"); 138 plist_add_sub_key_el(dict, "Request");
85 plist_add_sub_string_el(dict, "StopSession"); 139 plist_add_sub_string_el(dict, "StopSession");
86 plist_add_sub_key_el(dict, "SessionID"); 140 plist_add_sub_key_el(dict, "SessionID");
87 plist_add_sub_string_el(dict, control->session_id); 141 plist_add_sub_string_el(dict, client->session_id);
88 142
89 log_dbg_msg(DBGMASK_LOCKDOWND, "iphone_lckd_stop_session() called\n"); 143 log_dbg_msg(DBGMASK_LOCKDOWND, "iphone_lckd_stop_session() called\n");
90 144
91 ret = iphone_lckd_send(control, dict); 145 ret = lockdownd_send(client, dict);
92 146
93 plist_free(dict); 147 plist_free(dict);
94 dict = NULL; 148 dict = NULL;
95 149
96 ret = iphone_lckd_recv(control, &dict); 150 ret = lockdownd_recv(client, &dict);
97 151
98 if (!dict) { 152 if (!dict) {
99 log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_stop_session(): IPHONE_E_PLIST_ERROR\n"); 153 log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_stop_session(): IPHONE_E_PLIST_ERROR\n");
100 return; // IPHONE_E_PLIST_ERROR; 154 return IPHONE_E_PLIST_ERROR;
101 } 155 }
102 156
103 plist_t query_node = plist_find_node_by_string(dict, "StopSession"); 157 ret = IPHONE_E_UNKNOWN_ERROR;
104 plist_t result_node = plist_get_next_sibling(query_node); 158 if (lockdown_check_result(dict, "StopSession") == RESULT_SUCCESS) {
105 plist_t value_node = plist_get_next_sibling(result_node); 159 log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_stop_session(): success\n");
106 160 ret = IPHONE_E_SUCCESS;
107 plist_type result_type = plist_get_node_type(result_node);
108 plist_type value_type = plist_get_node_type(value_node);
109
110 if (result_type == PLIST_KEY && value_type == PLIST_STRING) {
111
112 char *result_value = NULL;
113 char *value_value = NULL;
114
115 plist_get_key_val(result_node, &result_value);
116 plist_get_string_val(value_node, &value_value);
117
118 if (!strcmp(result_value, "Result") && !strcmp(value_value, "Success")) {
119 log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_stop_session(): success\n");
120 ret = IPHONE_E_SUCCESS;
121 }
122 free(result_value);
123 free(value_value);
124 } 161 }
125 plist_free(dict); 162 plist_free(dict);
126 dict = NULL; 163 dict = NULL;
127 164
128 return; // ret; 165 return ret;
129} 166}
130 167
131/** 168/**
@@ -135,16 +172,17 @@ static void iphone_lckd_stop_session(iphone_lckd_client_t control)
135 * 172 *
136 * @param client The lockdown client 173 * @param client The lockdown client
137 */ 174 */
138static void iphone_lckd_stop_SSL_session(iphone_lckd_client_t client) 175static iphone_error_t lockdownd_stop_ssl_session(lockdownd_client_t client)
139{ 176{
140 if (!client) { 177 if (!client) {
141 log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_stop_SSL_session(): invalid argument!\n"); 178 log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_stop_ssl_session(): invalid argument!\n");
142 return; 179 return IPHONE_E_INVALID_ARG;
143 } 180 }
181 iphone_error_t ret = IPHONE_E_SUCCESS;
144 182
145 if (client->in_SSL) { 183 if (client->in_SSL) {
146 log_dbg_msg(DBGMASK_LOCKDOWND, "Stopping SSL Session\n"); 184 log_dbg_msg(DBGMASK_LOCKDOWND, "Stopping SSL Session\n");
147 iphone_lckd_stop_session(client); 185 ret = lockdownd_stop_session(client);
148 log_dbg_msg(DBGMASK_LOCKDOWND, "Sending SSL close notify\n"); 186 log_dbg_msg(DBGMASK_LOCKDOWND, "Sending SSL close notify\n");
149 gnutls_bye(*client->ssl_session, GNUTLS_SHUT_RDWR); 187 gnutls_bye(*client->ssl_session, GNUTLS_SHUT_RDWR);
150 } 188 }
@@ -154,27 +192,26 @@ static void iphone_lckd_stop_SSL_session(iphone_lckd_client_t client)
154 } 192 }
155 client->in_SSL = 0; 193 client->in_SSL = 0;
156 194
157 return; 195 return ret;
158} 196}
159 197
160/** Closes the lockdownd client and does the necessary housekeeping. 198/** Closes the lockdownd client and does the necessary housekeeping.
161 * 199 *
162 * @param control The lockdown client 200 * @param client The lockdown client
163 */ 201 */
164iphone_error_t iphone_lckd_free_client(iphone_lckd_client_t client) 202iphone_error_t lockdownd_free_client(lockdownd_client_t client)
165{ 203{
166 if (!client) 204 if (!client)
167 return IPHONE_E_INVALID_ARG; 205 return IPHONE_E_INVALID_ARG;
168 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; 206 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
169 207
170 iphone_lckd_stop_SSL_session(client); 208 lockdownd_stop_ssl_session(client);
171 209
172 if (client->sfd > 0) { 210 if (client->sfd > 0) {
173 lockdownd_close(client); 211 lockdownd_goodbye(client);
174 212
175 // IMO, read of final "sessionUpcall connection closed" packet 213 // IMO, read of final "sessionUpcall connection closed" packet
176 // should come here instead of in iphone_free_device 214 // should come here instead of in iphone_free_device
177
178 ret = usbmuxd_disconnect(client->sfd); 215 ret = usbmuxd_disconnect(client->sfd);
179 } 216 }
180 217
@@ -185,12 +222,11 @@ iphone_error_t iphone_lckd_free_client(iphone_lckd_client_t client)
185/** Polls the iPhone for lockdownd data. 222/** Polls the iPhone for lockdownd data.
186 * 223 *
187 * @param control The lockdownd client 224 * @param control The lockdownd client
188 * @param dump_data The pointer to the location of the buffer in which to store 225 * @param plist The plist to store the received data
189 * the received data
190 * 226 *
191 * @return The number of bytes received 227 * @return an error code (IPHONE_E_SUCCESS on success)
192 */ 228 */
193iphone_error_t iphone_lckd_recv(iphone_lckd_client_t client, plist_t * plist) 229iphone_error_t lockdownd_recv(lockdownd_client_t client, plist_t *plist)
194{ 230{
195 if (!client || !plist || (plist && *plist)) 231 if (!client || !plist || (plist && *plist))
196 return IPHONE_E_INVALID_ARG; 232 return IPHONE_E_INVALID_ARG;
@@ -265,7 +301,7 @@ iphone_error_t iphone_lckd_recv(iphone_lckd_client_t client, plist_t * plist)
265 * 301 *
266 * @return an error code (IPHONE_E_SUCCESS on success) 302 * @return an error code (IPHONE_E_SUCCESS on success)
267 */ 303 */
268iphone_error_t iphone_lckd_send(iphone_lckd_client_t client, plist_t plist) 304iphone_error_t lockdownd_send(lockdownd_client_t client, plist_t plist)
269{ 305{
270 if (!client || !plist) 306 if (!client || !plist)
271 return IPHONE_E_INVALID_ARG; 307 return IPHONE_E_INVALID_ARG;
@@ -278,7 +314,6 @@ iphone_error_t iphone_lckd_send(iphone_lckd_client_t client, plist_t plist)
278 plist_to_xml(plist, &XMLContent, &length); 314 plist_to_xml(plist, &XMLContent, &length);
279 log_dbg_msg(DBGMASK_LOCKDOWND, "Send msg :\nsize : %i\nbuffer :\n%s\n", length, XMLContent); 315 log_dbg_msg(DBGMASK_LOCKDOWND, "Send msg :\nsize : %i\nbuffer :\n%s\n", length, XMLContent);
280 316
281
282 real_query = (char *) malloc(sizeof(char) * (length + 4)); 317 real_query = (char *) malloc(sizeof(char) * (length + 4));
283 length = htonl(length); 318 length = htonl(length);
284 memcpy(real_query, &length, sizeof(length)); 319 memcpy(real_query, &length, sizeof(length));
@@ -310,15 +345,13 @@ iphone_error_t iphone_lckd_send(iphone_lckd_client_t client, plist_t plist)
310 345
311/** Initiates the handshake for the lockdown session. Part of the lockdownd handshake. 346/** Initiates the handshake for the lockdown session. Part of the lockdownd handshake.
312 * 347 *
313 * @note You most likely want lockdownd_init unless you are doing something special. 348 * @param client The lockdownd client
314 *
315 * @param control The lockdownd client
316 * 349 *
317 * @return 1 on success and 0 on failure. 350 * @return an error code (IPHONE_E_SUCCESS on success)
318 */ 351 */
319iphone_error_t lockdownd_hello(iphone_lckd_client_t control) 352iphone_error_t lockdownd_query_type(lockdownd_client_t client)
320{ 353{
321 if (!control) 354 if (!client)
322 return IPHONE_E_INVALID_ARG; 355 return IPHONE_E_INVALID_ARG;
323 356
324 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; 357 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
@@ -327,72 +360,60 @@ iphone_error_t lockdownd_hello(iphone_lckd_client_t control)
327 plist_add_sub_key_el(dict, "Request"); 360 plist_add_sub_key_el(dict, "Request");
328 plist_add_sub_string_el(dict, "QueryType"); 361 plist_add_sub_string_el(dict, "QueryType");
329 362
330 log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_hello() called\n"); 363 log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_query_type() called\n");
331 ret = iphone_lckd_send(control, dict); 364 ret = lockdownd_send(client, dict);
332 365
333 plist_free(dict); 366 plist_free(dict);
334 dict = NULL; 367 dict = NULL;
335 368
336 ret = iphone_lckd_recv(control, &dict); 369 ret = lockdownd_recv(client, &dict);
337 370
338 if (IPHONE_E_SUCCESS != ret) 371 if (IPHONE_E_SUCCESS != ret)
339 return ret; 372 return ret;
340 373
341 plist_t query_node = plist_find_node_by_string(dict, "QueryType"); 374 ret = IPHONE_E_UNKNOWN_ERROR;
342 plist_t result_node = plist_get_next_sibling(query_node); 375 if (lockdown_check_result(dict, "QueryType") == RESULT_SUCCESS) {
343 plist_t value_node = plist_get_next_sibling(result_node); 376 log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_query_type(): success\n");
344 377 ret = IPHONE_E_SUCCESS;
345 plist_type result_type = plist_get_node_type(result_node);
346 plist_type value_type = plist_get_node_type(value_node);
347
348 if (result_type == PLIST_KEY && value_type == PLIST_STRING) {
349
350 char *result_value = NULL;
351 char *value_value = NULL;
352
353 plist_get_key_val(result_node, &result_value);
354 plist_get_string_val(value_node, &value_value);
355
356 if (!strcmp(result_value, "Result") && !strcmp(value_value, "Success")) {
357 log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_hello(): success\n");
358 ret = IPHONE_E_SUCCESS;
359 }
360 free(result_value);
361 free(value_value);
362 } 378 }
363
364 plist_free(dict); 379 plist_free(dict);
365 dict = NULL; 380 dict = NULL;
366 381
367 return ret; 382 return ret;
368} 383}
369 384
370/** Generic function to handle simple (key, value) requests. 385/** Retrieves a preferences plist using an optional domain and/or key name.
371 * 386 *
372 * @param control an initialized lockdownd client. 387 * @param client an initialized lockdownd client.
373 * @param key the key to request 388 * @param domain the domain to query on or NULL for global domain
374 * @param value a pointer to the requested value 389 * @param key the key name to request or NULL to query for all keys
390 * @param value_node a plist node representing the result value node
375 * 391 *
376 * @return IPHONE_E_SUCCESS on success. 392 * @return an error code (IPHONE_E_SUCCESS on success)
377 */ 393 */
378iphone_error_t lockdownd_generic_get_value(iphone_lckd_client_t control, const char *req_key, const char *req_string, 394iphone_error_t lockdownd_get_value(lockdownd_client_t client, const char *domain, const char *key, plist_t *value_node)
379 gnutls_datum_t * value)
380{ 395{
381 if (!control || !req_key || !value || value->data) 396 if (!client)
382 return IPHONE_E_INVALID_ARG; 397 return IPHONE_E_INVALID_ARG;
383 398
384 plist_t dict = NULL; 399 plist_t dict = NULL;
385 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; 400 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
386 401
387 /* Setup DevicePublicKey request plist */ 402 /* setup request plist */
388 dict = plist_new_dict(); 403 dict = plist_new_dict();
389 plist_add_sub_key_el(dict, req_key); 404 if (domain) {
390 plist_add_sub_string_el(dict, req_string); 405 plist_add_sub_key_el(dict, "Domain");
406 plist_add_sub_string_el(dict, domain);
407 }
408 if (key) {
409 plist_add_sub_key_el(dict, "Key");
410 plist_add_sub_string_el(dict, key);
411 }
391 plist_add_sub_key_el(dict, "Request"); 412 plist_add_sub_key_el(dict, "Request");
392 plist_add_sub_string_el(dict, "GetValue"); 413 plist_add_sub_string_el(dict, "GetValue");
393 414
394 /* send to iPhone */ 415 /* send to device */
395 ret = iphone_lckd_send(control, dict); 416 ret = lockdownd_send(client, dict);
396 417
397 plist_free(dict); 418 plist_free(dict);
398 dict = NULL; 419 dict = NULL;
@@ -400,71 +421,38 @@ iphone_error_t lockdownd_generic_get_value(iphone_lckd_client_t control, const c
400 if (ret != IPHONE_E_SUCCESS) 421 if (ret != IPHONE_E_SUCCESS)
401 return ret; 422 return ret;
402 423
403 /* Now get iPhone's answer */ 424 /* Now get device's answer */
404 ret = iphone_lckd_recv(control, &dict); 425 ret = lockdownd_recv(client, &dict);
405
406 if (ret != IPHONE_E_SUCCESS) 426 if (ret != IPHONE_E_SUCCESS)
407 return ret; 427 return ret;
408 428
409 plist_t query_node = plist_find_node_by_string(dict, "GetValue"); 429 if (lockdown_check_result(dict, "GetValue") == RESULT_SUCCESS) {
410 plist_t result_key_node = plist_get_next_sibling(query_node); 430 log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_get_value(): success\n");
411 plist_t result_value_node = plist_get_next_sibling(result_key_node); 431 ret = IPHONE_E_SUCCESS;
412
413 plist_type result_key_type = plist_get_node_type(result_key_node);
414 plist_type result_value_type = plist_get_node_type(result_value_node);
415
416 if (result_key_type == PLIST_KEY && result_value_type == PLIST_STRING) {
417
418 char *result_key = NULL;
419 char *result_value = NULL;
420 ret = IPHONE_E_DICT_ERROR;
421
422 plist_get_key_val(result_key_node, &result_key);
423 plist_get_string_val(result_value_node, &result_value);
424
425 if (!strcmp(result_key, "Result") && !strcmp(result_value, "Success")) {
426 log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_generic_get_value(): success\n");
427 ret = IPHONE_E_SUCCESS;
428 }
429 free(result_key);
430 free(result_value);
431 } 432 }
432 if (ret != IPHONE_E_SUCCESS) { 433 if (ret != IPHONE_E_SUCCESS) {
434 plist_free(dict);
433 return ret; 435 return ret;
434 } 436 }
435 437
436 plist_t value_key_node = plist_find_node_by_key(dict, "Value");//plist_get_next_sibling(result_value_node); 438 plist_t value_key_node = plist_find_node_by_key(dict, "Value");
437 plist_t value_value_node = plist_get_next_sibling(value_key_node); 439 plist_t value_value_node = plist_get_next_sibling(value_key_node);
438 440
439 plist_type value_key_type = plist_get_node_type(value_key_node); 441 plist_type value_key_type = plist_get_node_type(value_key_node);
440 442
441 if (value_key_type == PLIST_KEY) { 443 if (value_key_type == PLIST_KEY) {
442
443 char *result_key = NULL; 444 char *result_key = NULL;
444 plist_get_key_val(value_key_node, &result_key); 445 plist_get_key_val(value_key_node, &result_key);
445 446
446 if (!strcmp(result_key, "Value")) { 447 if (!strcmp(result_key, "Value")) {
447 log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_generic_get_value(): success\n"); 448 char *buf = NULL;
448 449 uint32_t length;
449 plist_type value_value_type = plist_get_node_type(value_value_node); 450 log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_get_value(): has a value\n");
450 if (PLIST_STRING == value_value_type) { 451
451 char *value_value = NULL; 452 /* FIXME: libplist does not offer cloning of nodes, use serialization */
452 plist_get_string_val(value_value_node, &value_value); 453 plist_to_bin(value_value_node, &buf, &length);
453 454 plist_from_bin(buf, length, value_node);
454 value->data = (unsigned char*)value_value; 455 free(buf);
455 value->size = strlen(value_value);
456 ret = IPHONE_E_SUCCESS;
457 }
458
459 if (PLIST_DATA == value_value_type) {
460 char *value_value = NULL;
461 uint64_t size = 0;
462 plist_get_data_val(value_value_node, &value_value, &size);
463
464 value->data = (unsigned char*)value_value;
465 value->size = size;
466 ret = IPHONE_E_SUCCESS;
467 }
468 } 456 }
469 free(result_key); 457 free(result_key);
470 } 458 }
@@ -473,69 +461,109 @@ iphone_error_t lockdownd_generic_get_value(iphone_lckd_client_t control, const c
473 return ret; 461 return ret;
474} 462}
475 463
476/** Askes for the device's unique id. Part of the lockdownd handshake. 464/** Asks for the device's unique id. Part of the lockdownd handshake.
477 *
478 * @note You most likely want lockdownd_init unless you are doing something special.
479 * 465 *
480 * @return 1 on success and 0 on failure. 466 * @return an error code (IPHONE_E_SUCCESS on success)
481 */ 467 */
482iphone_error_t lockdownd_get_device_uid(iphone_lckd_client_t control, char **uid) 468iphone_error_t lockdownd_get_device_uid(lockdownd_client_t client, char **uid)
483{ 469{
484 gnutls_datum_t temp = { NULL, 0 }; 470 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
485 iphone_error_t ret = lockdownd_generic_get_value(control, "Key", "UniqueDeviceID", &temp); 471 plist_t value = NULL;
486 *uid = (char*)temp.data; 472 value = plist_new_dict();
473
474 ret = lockdownd_get_value(client, NULL, "UniqueDeviceID", &value);
475 if (ret != IPHONE_E_SUCCESS) {
476 return ret;
477 }
478 plist_get_string_val(value, uid);
479
480 plist_free(value);
481 value = NULL;
487 return ret; 482 return ret;
488} 483}
489 484
490/** Askes for the device's public key. Part of the lockdownd handshake. 485/** Askes for the device's public key. Part of the lockdownd handshake.
491 * 486 *
492 * @note You most likely want lockdownd_init unless you are doing something special. 487 * @return an error code (IPHONE_E_SUCCESS on success)
493 *
494 * @return IPHONE_E_SUCCESS on succes or an error value < 0 on failure.
495 */ 488 */
496iphone_error_t lockdownd_get_device_public_key(iphone_lckd_client_t control, gnutls_datum_t * public_key) 489iphone_error_t lockdownd_get_device_public_key(lockdownd_client_t client, gnutls_datum_t * public_key)
497{ 490{
498 return lockdownd_generic_get_value(control, "Key", "DevicePublicKey", public_key); 491 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
492 plist_t value = NULL;
493 char *value_value = NULL;
494 uint64_t size = 0;
495 value = plist_new_dict();
496
497 ret = lockdownd_get_value(client, NULL, "DevicePublicKey", &value);
498 if (ret != IPHONE_E_SUCCESS) {
499 return ret;
500 }
501 plist_get_data_val(value, &value_value, &size);
502 public_key->data = (unsigned char*)value_value;
503 public_key->size = size;
504
505 plist_free(value);
506 value = NULL;
507
508 return ret;
499} 509}
500 510
501/** Askes for the device's name. 511/** Askes for the device's name.
502 * 512 *
503 * @return IPHONE_E_SUCCESS on succes or an error value < 0 on failure. 513 * @param client The pointer to the location of the new lockdownd_client
514 *
515 *
516 * @return an error code (IPHONE_E_SUCCESS on success)
504 */ 517 */
505iphone_error_t lockdownd_get_device_name(iphone_lckd_client_t control, char **device_name) 518iphone_error_t lockdownd_get_device_name(lockdownd_client_t client, char **device_name)
506{ 519{
507 gnutls_datum_t temp = { NULL, 0 }; 520 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
508 iphone_error_t res = lockdownd_generic_get_value(control, "Key", "DeviceName", &temp); 521 plist_t value = NULL;
509 log_debug_msg("%s: %s\n", __func__, temp.data); 522 value = plist_new_dict();
510 *device_name = (char*)temp.data; 523
511 return res; 524 ret = lockdownd_get_value(client, NULL, "DeviceName", &value);
525 if (ret != IPHONE_E_SUCCESS) {
526 return ret;
527 }
528 plist_get_string_val(value, device_name);
529 log_debug_msg("%s: %s\n", __func__, device_name);
530
531 plist_free(value);
532 value = NULL;
533
534 return ret;
512} 535}
513 536
514/** Completes the entire lockdownd handshake. 537/** Creates a lockdownd client for the give iPhone
515 * 538 *
516 * @param phone The iPhone 539 * @param phone The iPhone to create a lockdownd client for
517 * @param lockdownd_client The pointer to the location of the lockdownd_client 540 * @param client The pointer to the location of the new lockdownd_client
518 * 541 *
519 * @return 1 on success and 0 on failure 542 * @return an error code (IPHONE_E_SUCCESS on success)
520 */ 543 */
521iphone_error_t iphone_lckd_new_client(iphone_device_t device, iphone_lckd_client_t * client) 544iphone_error_t lockdownd_new_client(iphone_device_t device, lockdownd_client_t *client)
522{ 545{
523 if (!device || !client || (client && *client)) 546 if (!device || !client || (client && *client))
524 return IPHONE_E_INVALID_ARG; 547 return IPHONE_E_INVALID_ARG;
525 iphone_error_t ret = IPHONE_E_SUCCESS; 548 iphone_error_t ret = IPHONE_E_SUCCESS;
526 char *host_id = NULL; 549 char *host_id = NULL;
527 550
528 iphone_lckd_client_t client_loc = new_lockdownd_client(device); 551 int sfd = usbmuxd_connect(device->handle, 0xf27e);
529 if (!client_loc) { 552 if (sfd < 0) {
530 log_debug_msg("FATAL: lockdownd client could not be created!\n"); 553 log_debug_msg("%s: could not connect to lockdownd (device handle %d)\n", __func__, device->handle);
531 return IPHONE_E_UNKNOWN_ERROR; 554 return IPHONE_E_UNKNOWN_ERROR;
532 } 555 }
533 if (IPHONE_E_SUCCESS != lockdownd_hello(client_loc)) { 556
534 log_debug_msg("Hello failed in the lockdownd client.\n"); 557 lockdownd_client_t client_loc = (lockdownd_client_t) malloc(sizeof(struct lockdownd_client_int));
558 client_loc->sfd = sfd;
559 client_loc->ssl_session = (gnutls_session_t *) malloc(sizeof(gnutls_session_t));
560 client_loc->in_SSL = 0;
561
562 if (IPHONE_E_SUCCESS != lockdownd_query_type(client_loc)) {
563 log_debug_msg("QueryType failed in the lockdownd client.\n");
535 ret = IPHONE_E_NOT_ENOUGH_DATA; 564 ret = IPHONE_E_NOT_ENOUGH_DATA;
536 } 565 }
537 566
538
539 char *uid = NULL; 567 char *uid = NULL;
540 ret = lockdownd_get_device_uid(client_loc, &uid); 568 ret = lockdownd_get_device_uid(client_loc, &uid);
541 if (IPHONE_E_SUCCESS != ret) { 569 if (IPHONE_E_SUCCESS != ret) {
@@ -549,7 +577,7 @@ iphone_error_t iphone_lckd_new_client(iphone_device_t device, iphone_lckd_client
549 } 577 }
550 578
551 if (IPHONE_E_SUCCESS == ret && !is_device_known(uid)) 579 if (IPHONE_E_SUCCESS == ret && !is_device_known(uid))
552 ret = lockdownd_pair_device(client_loc, uid, host_id); 580 ret = lockdownd_pair(client_loc, uid, host_id);
553 581
554 if (uid) { 582 if (uid) {
555 free(uid); 583 free(uid);
@@ -557,7 +585,7 @@ iphone_error_t iphone_lckd_new_client(iphone_device_t device, iphone_lckd_client
557 } 585 }
558 586
559 if (IPHONE_E_SUCCESS == ret) { 587 if (IPHONE_E_SUCCESS == ret) {
560 ret = lockdownd_start_SSL_session(client_loc, host_id); 588 ret = lockdownd_start_ssl_session(client_loc, host_id);
561 if (IPHONE_E_SUCCESS != ret) { 589 if (IPHONE_E_SUCCESS != ret) {
562 ret = IPHONE_E_SSL_ERROR; 590 ret = IPHONE_E_SSL_ERROR;
563 log_debug_msg("SSL Session opening failed.\n"); 591 log_debug_msg("SSL Session opening failed.\n");
@@ -578,11 +606,9 @@ iphone_error_t iphone_lckd_new_client(iphone_device_t device, iphone_lckd_client
578/** Generates the appropriate keys and pairs the device. It's part of the 606/** Generates the appropriate keys and pairs the device. It's part of the
579 * lockdownd handshake. 607 * lockdownd handshake.
580 * 608 *
581 * @note You most likely want lockdownd_init unless you are doing something special. 609 * @return an error code (IPHONE_E_SUCCESS on success)
582 *
583 * @return 1 on success and 0 on failure
584 */ 610 */
585iphone_error_t lockdownd_pair_device(iphone_lckd_client_t control, char *uid, char *host_id) 611iphone_error_t lockdownd_pair(lockdownd_client_t client, char *uid, char *host_id)
586{ 612{
587 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; 613 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
588 plist_t dict = NULL; 614 plist_t dict = NULL;
@@ -593,7 +619,7 @@ iphone_error_t lockdownd_pair_device(iphone_lckd_client_t control, char *uid, ch
593 gnutls_datum_t root_cert = { NULL, 0 }; 619 gnutls_datum_t root_cert = { NULL, 0 };
594 gnutls_datum_t public_key = { NULL, 0 }; 620 gnutls_datum_t public_key = { NULL, 0 };
595 621
596 ret = lockdownd_get_device_public_key(control, &public_key); 622 ret = lockdownd_get_device_public_key(client, &public_key);
597 if (ret != IPHONE_E_SUCCESS) { 623 if (ret != IPHONE_E_SUCCESS) {
598 log_debug_msg("Device refused to send public key.\n"); 624 log_debug_msg("Device refused to send public key.\n");
599 return ret; 625 return ret;
@@ -623,7 +649,7 @@ iphone_error_t lockdownd_pair_device(iphone_lckd_client_t control, char *uid, ch
623 plist_add_sub_string_el(dict, "Pair"); 649 plist_add_sub_string_el(dict, "Pair");
624 650
625 /* send to iPhone */ 651 /* send to iPhone */
626 ret = iphone_lckd_send(control, dict); 652 ret = lockdownd_send(client, dict);
627 plist_free(dict); 653 plist_free(dict);
628 dict = NULL; 654 dict = NULL;
629 655
@@ -631,43 +657,24 @@ iphone_error_t lockdownd_pair_device(iphone_lckd_client_t control, char *uid, ch
631 return ret; 657 return ret;
632 658
633 /* Now get iPhone's answer */ 659 /* Now get iPhone's answer */
634 ret = iphone_lckd_recv(control, &dict); 660 ret = lockdownd_recv(client, &dict);
635 661
636 if (ret != IPHONE_E_SUCCESS) 662 if (ret != IPHONE_E_SUCCESS)
637 return ret; 663 return ret;
638 664
639 plist_t query_node = plist_find_node_by_string(dict, "Pair"); 665 if (lockdown_check_result(dict, "Pair") == RESULT_SUCCESS) {
640 plist_t result_key_node = plist_get_next_sibling(query_node); 666 ret = IPHONE_E_SUCCESS;
641 plist_t result_value_node = plist_get_next_sibling(result_key_node);
642
643 plist_type result_key_type = plist_get_node_type(result_key_node);
644 plist_type result_value_type = plist_get_node_type(result_value_node);
645
646 if (result_key_type == PLIST_KEY && result_value_type == PLIST_STRING) {
647
648 char *result_key = NULL;
649 char *result_value = NULL;
650
651 plist_get_key_val(result_key_node, &result_key);
652 plist_get_string_val(result_value_node, &result_value);
653
654 if (!strcmp(result_key, "Result") && !strcmp(result_value, "Success")) {
655 ret = IPHONE_E_SUCCESS;
656 }
657
658 free(result_key);
659 free(result_value);
660 } 667 }
661 plist_free(dict); 668 plist_free(dict);
662 dict = NULL; 669 dict = NULL;
663 670
664 /* store public key in config if pairing succeeded */ 671 /* store public key in config if pairing succeeded */
665 if (ret == IPHONE_E_SUCCESS) { 672 if (ret == IPHONE_E_SUCCESS) {
666 log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_pair_device: pair success\n"); 673 log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_pair: pair success\n");
667 store_device_public_key(uid, public_key); 674 store_device_public_key(uid, public_key);
668 ret = IPHONE_E_SUCCESS; 675 ret = IPHONE_E_SUCCESS;
669 } else { 676 } else {
670 log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_pair_device: pair failure\n"); 677 log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_pair: pair failure\n");
671 ret = IPHONE_E_PAIRING_FAILED; 678 ret = IPHONE_E_PAIRING_FAILED;
672 } 679 }
673 free(public_key.data); 680 free(public_key.data);
@@ -678,12 +685,14 @@ iphone_error_t lockdownd_pair_device(iphone_lckd_client_t control, char *uid, ch
678 * Performs the Goodbye Request to tell the device the communication 685 * Performs the Goodbye Request to tell the device the communication
679 * session is now closed. 686 * session is now closed.
680 * 687 *
681 * @param control The lockdown client 688 * @param client The lockdown client
689 *
690 * @return an error code (IPHONE_E_SUCCESS on success)
682 */ 691 */
683void lockdownd_close(iphone_lckd_client_t control) 692iphone_error_t lockdownd_goodbye(lockdownd_client_t client)
684{ 693{
685 if (!control) 694 if (!client)
686 return; //IPHONE_E_INVALID_ARG; 695 return IPHONE_E_INVALID_ARG;
687 696
688 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; 697 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
689 698
@@ -691,49 +700,32 @@ void lockdownd_close(iphone_lckd_client_t control)
691 plist_add_sub_key_el(dict, "Request"); 700 plist_add_sub_key_el(dict, "Request");
692 plist_add_sub_string_el(dict, "Goodbye"); 701 plist_add_sub_string_el(dict, "Goodbye");
693 702
694 log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_close() called\n"); 703 log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_goodbye() called\n");
695 704
696 ret = iphone_lckd_send(control, dict); 705 ret = lockdownd_send(client, dict);
697 plist_free(dict); 706 plist_free(dict);
698 dict = NULL; 707 dict = NULL;
699 708
700 ret = iphone_lckd_recv(control, &dict); 709 ret = lockdownd_recv(client, &dict);
701 710
702 if (!dict) { 711 if (!dict) {
703 log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_close(): IPHONE_E_PLIST_ERROR\n"); 712 log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_goodbye(): IPHONE_E_PLIST_ERROR\n");
704 return; // IPHONE_E_PLIST_ERROR; 713 return IPHONE_E_PLIST_ERROR;
705 } 714 }
706 715
707 plist_t query_node = plist_find_node_by_string(dict, "Goodbye"); 716 if (lockdown_check_result(dict, "Goodbye") == RESULT_SUCCESS) {
708 plist_t result_node = plist_get_next_sibling(query_node); 717 log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_goodbye(): success\n");
709 plist_t value_node = plist_get_next_sibling(result_node); 718 ret = IPHONE_E_SUCCESS;
710
711 plist_type result_type = plist_get_node_type(result_node);
712 plist_type value_type = plist_get_node_type(value_node);
713
714 if (result_type == PLIST_KEY && value_type == PLIST_STRING) {
715 char *result_value = NULL;
716 char *value_value = NULL;
717
718 plist_get_key_val(result_node, &result_value);
719 plist_get_string_val(value_node, &value_value);
720
721 if (!strcmp(result_value, "Result") && !strcmp(value_value, "Success")) {
722 log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_close(): success\n");
723 ret = IPHONE_E_SUCCESS;
724 }
725 free(result_value);
726 free(value_value);
727 } 719 }
728 plist_free(dict); 720 plist_free(dict);
729 dict = NULL; 721 dict = NULL;
730 return; // ret; 722 return ret;
731} 723}
732 724
733/** Generates the device certificate from the public key as well as the host 725/** Generates the device certificate from the public key as well as the host
734 * and root certificates. 726 * and root certificates.
735 * 727 *
736 * @return IPHONE_E_SUCCESS on success. 728 * @return an error code (IPHONE_E_SUCCESS on success)
737 */ 729 */
738iphone_error_t lockdownd_gen_pair_cert(gnutls_datum_t public_key, gnutls_datum_t * odevice_cert, 730iphone_error_t lockdownd_gen_pair_cert(gnutls_datum_t public_key, gnutls_datum_t * odevice_cert,
739 gnutls_datum_t * ohost_cert, gnutls_datum_t * oroot_cert) 731 gnutls_datum_t * ohost_cert, gnutls_datum_t * oroot_cert)
@@ -798,7 +790,7 @@ iphone_error_t lockdownd_gen_pair_cert(gnutls_datum_t public_key, gnutls_datum_t
798 gnutls_x509_privkey_init(&root_privkey); 790 gnutls_x509_privkey_init(&root_privkey);
799 gnutls_x509_privkey_init(&host_privkey); 791 gnutls_x509_privkey_init(&host_privkey);
800 792
801 ret = get_keys_and_certs( root_privkey, root_cert, host_privkey, host_cert); 793 ret = get_keys_and_certs(root_privkey, root_cert, host_privkey, host_cert);
802 794
803 if (IPHONE_E_SUCCESS == ret) { 795 if (IPHONE_E_SUCCESS == ret) {
804 796
@@ -853,18 +845,18 @@ iphone_error_t lockdownd_gen_pair_cert(gnutls_datum_t public_key, gnutls_datum_t
853 845
854/** Starts SSL communication with lockdownd after the iPhone has been paired. 846/** Starts SSL communication with lockdownd after the iPhone has been paired.
855 * 847 *
856 * @param control The lockdownd client 848 * @param client The lockdownd client
857 * @param HostID The HostID used with this phone 849 * @param HostID The HostID used with this phone
858 * 850 *
859 * @return 1 on success and 0 on failure 851 * @return an error code (IPHONE_E_SUCCESS on success)
860 */ 852 */
861iphone_error_t lockdownd_start_SSL_session(iphone_lckd_client_t control, const char *HostID) 853iphone_error_t lockdownd_start_ssl_session(lockdownd_client_t client, const char *HostID)
862{ 854{
863 plist_t dict = NULL; 855 plist_t dict = NULL;
864 uint32_t return_me = 0; 856 uint32_t return_me = 0;
865 857
866 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; 858 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
867 control->session_id[0] = '\0'; 859 client->session_id[0] = '\0';
868 860
869 /* Setup DevicePublicKey request plist */ 861 /* Setup DevicePublicKey request plist */
870 dict = plist_new_dict(); 862 dict = plist_new_dict();
@@ -873,137 +865,101 @@ iphone_error_t lockdownd_start_SSL_session(iphone_lckd_client_t control, const c
873 plist_add_sub_key_el(dict, "Request"); 865 plist_add_sub_key_el(dict, "Request");
874 plist_add_sub_string_el(dict, "StartSession"); 866 plist_add_sub_string_el(dict, "StartSession");
875 867
876 ret = iphone_lckd_send(control, dict); 868 ret = lockdownd_send(client, dict);
877 plist_free(dict); 869 plist_free(dict);
878 dict = NULL; 870 dict = NULL;
879 871
880 if (ret != IPHONE_E_SUCCESS) 872 if (ret != IPHONE_E_SUCCESS)
881 return ret; 873 return ret;
882 874
883 ret = iphone_lckd_recv(control, &dict); 875 ret = lockdownd_recv(client, &dict);
884 876
885 if (!dict) 877 if (!dict)
886 return IPHONE_E_PLIST_ERROR; 878 return IPHONE_E_PLIST_ERROR;
887 879
888 plist_t request_node = plist_get_dict_el_from_key(dict, "Request"); 880 if (lockdown_check_result(dict, "StartSession") == RESULT_FAILURE) {
889 plist_t result_node = plist_get_dict_el_from_key(dict, "Result"); 881 plist_t error_node = plist_get_dict_el_from_key(dict, "Error");
890 882 if (error_node && PLIST_STRING == plist_get_node_type(error_node)) {
891 if (request_node && PLIST_STRING == plist_get_node_type(request_node) && 883 char *error = NULL;
892 result_node && PLIST_STRING == plist_get_node_type(result_node)){ 884 plist_get_string_val(error_node, &error);
893 885
894 char *request = NULL; 886 if (!strcmp(error, "InvalidHostID")) {
895 char *result = NULL; 887 //hostid is unknown. Pair and try again
896 888 char *uid = NULL;
897 plist_get_string_val(request_node, &request); 889 char* host_id = get_host_id();
898 plist_get_string_val(result_node, &result); 890 if (IPHONE_E_SUCCESS == lockdownd_get_device_uid(client, &uid) ) {
899 891 if (IPHONE_E_SUCCESS == lockdownd_pair(client, uid, host_id) ) {
900 if (!strcmp(request, "StartSession")) { 892 //start session again
901 if (!strcmp(result, "Failure")) { 893 plist_free(dict);
902 894 dict = plist_new_dict();
903 plist_t error_node = plist_get_dict_el_from_key(dict, "Error"); 895 plist_add_sub_key_el(dict, "HostID");
904 if (error_node && PLIST_STRING == plist_get_node_type(error_node)) { 896 plist_add_sub_string_el(dict, HostID);
905 897 plist_add_sub_key_el(dict, "Request");
906 char *error = NULL; 898 plist_add_sub_string_el(dict, "StartSession");
907 plist_get_string_val(error_node, &error); 899
908 900 ret = lockdownd_send(client, dict);
909 if (!strcmp(error, "InvalidHostID")) { 901 plist_free(dict);
910 //hostid is not know. Pair and try again 902 dict = NULL;
911 char *uid = NULL; 903
912 char* host_id = get_host_id(); 904 ret = lockdownd_recv(client, &dict);
913 if (IPHONE_E_SUCCESS == lockdownd_get_device_uid(control, &uid) ) {
914 if (IPHONE_E_SUCCESS == lockdownd_pair_device(control, uid, host_id) ) {
915
916 //start session again
917 plist_free(dict);
918 dict = plist_new_dict();
919 plist_add_sub_key_el(dict, "HostID");
920 plist_add_sub_string_el(dict, HostID);
921 plist_add_sub_key_el(dict, "Request");
922 plist_add_sub_string_el(dict, "StartSession");
923
924 ret = iphone_lckd_send(control, dict);
925 plist_free(dict);
926 dict = NULL;
927
928 ret = iphone_lckd_recv(control, &dict);
929 }
930 }
931 free(uid);
932 free(host_id);
933 } 905 }
934 free(error);
935 } 906 }
907 free(uid);
908 free(host_id);
936 } 909 }
910 free(error);
937 } 911 }
938 free(request);
939 free(result);
940 } 912 }
941 913
942 plist_t query_node = plist_find_node_by_string(dict, "StartSession"); 914 ret = IPHONE_E_SSL_ERROR;
943 plist_t result_key_node = plist_get_next_sibling(query_node); 915 if (lockdown_check_result(dict, "StartSession") == RESULT_SUCCESS) {
944 plist_t result_value_node = plist_get_next_sibling(result_key_node); 916 // Set up GnuTLS...
945 917 //gnutls_anon_client_credentials_t anoncred;
946 plist_type result_key_type = plist_get_node_type(result_key_node); 918 gnutls_certificate_credentials_t xcred;
947 plist_type result_value_type = plist_get_node_type(result_value_node);
948
949 if (result_key_type == PLIST_KEY && result_value_type == PLIST_STRING) {
950 char *result_key = NULL;
951 char *result_value = NULL;
952
953 plist_get_key_val(result_key_node, &result_key);
954 plist_get_string_val(result_value_node, &result_value);
955
956 ret = IPHONE_E_SSL_ERROR;
957 if (!strcmp(result_key, "Result") && !strcmp(result_value, "Success")) {
958 // Set up GnuTLS...
959 //gnutls_anon_client_credentials_t anoncred;
960 gnutls_certificate_credentials_t xcred;
961
962 log_dbg_msg(DBGMASK_LOCKDOWND, "We started the session OK, now trying GnuTLS\n");
963 errno = 0;
964 gnutls_global_init();
965 //gnutls_anon_allocate_client_credentials(&anoncred);
966 gnutls_certificate_allocate_credentials(&xcred);
967 gnutls_certificate_set_x509_trust_file(xcred, "hostcert.pem", GNUTLS_X509_FMT_PEM);
968 gnutls_init(control->ssl_session, GNUTLS_CLIENT);
969 {
970 int protocol_priority[16] = { GNUTLS_SSL3, 0 };
971 int kx_priority[16] = { GNUTLS_KX_ANON_DH, GNUTLS_KX_RSA, 0 };
972 int cipher_priority[16] = { GNUTLS_CIPHER_AES_128_CBC, GNUTLS_CIPHER_AES_256_CBC, 0 };
973 int mac_priority[16] = { GNUTLS_MAC_SHA1, GNUTLS_MAC_MD5, 0 };
974 int comp_priority[16] = { GNUTLS_COMP_NULL, 0 };
975
976 gnutls_cipher_set_priority(*control->ssl_session, cipher_priority);
977 gnutls_compression_set_priority(*control->ssl_session, comp_priority);
978 gnutls_kx_set_priority(*control->ssl_session, kx_priority);
979 gnutls_protocol_set_priority(*control->ssl_session, protocol_priority);
980 gnutls_mac_set_priority(*control->ssl_session, mac_priority);
981 919
982 } 920 log_dbg_msg(DBGMASK_LOCKDOWND, "We started the session OK, now trying GnuTLS\n");
983 gnutls_credentials_set(*control->ssl_session, GNUTLS_CRD_CERTIFICATE, xcred); // this part is killing me. 921 errno = 0;
984 922 gnutls_global_init();
985 log_dbg_msg(DBGMASK_LOCKDOWND, "GnuTLS step 1...\n"); 923 //gnutls_anon_allocate_client_credentials(&anoncred);
986 gnutls_transport_set_ptr(*control->ssl_session, (gnutls_transport_ptr_t) control); 924 gnutls_certificate_allocate_credentials(&xcred);
987 log_dbg_msg(DBGMASK_LOCKDOWND, "GnuTLS step 2...\n"); 925 gnutls_certificate_set_x509_trust_file(xcred, "hostcert.pem", GNUTLS_X509_FMT_PEM);
988 gnutls_transport_set_push_function(*control->ssl_session, (gnutls_push_func) & lockdownd_secuwrite); 926 gnutls_init(client->ssl_session, GNUTLS_CLIENT);
989 log_dbg_msg(DBGMASK_LOCKDOWND, "GnuTLS step 3...\n"); 927 {
990 gnutls_transport_set_pull_function(*control->ssl_session, (gnutls_pull_func) & lockdownd_securead); 928 int protocol_priority[16] = { GNUTLS_SSL3, 0 };
991 log_dbg_msg(DBGMASK_LOCKDOWND, "GnuTLS step 4 -- now handshaking...\n"); 929 int kx_priority[16] = { GNUTLS_KX_ANON_DH, GNUTLS_KX_RSA, 0 };
992 930 int cipher_priority[16] = { GNUTLS_CIPHER_AES_128_CBC, GNUTLS_CIPHER_AES_256_CBC, 0 };
993 if (errno) 931 int mac_priority[16] = { GNUTLS_MAC_SHA1, GNUTLS_MAC_MD5, 0 };
994 log_dbg_msg(DBGMASK_LOCKDOWND, "WARN: errno says %s before handshake!\n", strerror(errno)); 932 int comp_priority[16] = { GNUTLS_COMP_NULL, 0 };
995 return_me = gnutls_handshake(*control->ssl_session); 933
996 log_dbg_msg(DBGMASK_LOCKDOWND, "GnuTLS handshake done...\n"); 934 gnutls_cipher_set_priority(*client->ssl_session, cipher_priority);
997 935 gnutls_compression_set_priority(*client->ssl_session, comp_priority);
998 if (return_me != GNUTLS_E_SUCCESS) { 936 gnutls_kx_set_priority(*client->ssl_session, kx_priority);
999 log_dbg_msg(DBGMASK_LOCKDOWND, "GnuTLS reported something wrong.\n"); 937 gnutls_protocol_set_priority(*client->ssl_session, protocol_priority);
1000 gnutls_perror(return_me); 938 gnutls_mac_set_priority(*client->ssl_session, mac_priority);
1001 log_dbg_msg(DBGMASK_LOCKDOWND, "oh.. errno says %s\n", strerror(errno)); 939 }
1002 return IPHONE_E_SSL_ERROR; 940 gnutls_credentials_set(*client->ssl_session, GNUTLS_CRD_CERTIFICATE, xcred); // this part is killing me.
1003 } else { 941
1004 control->in_SSL = 1; 942 log_dbg_msg(DBGMASK_LOCKDOWND, "GnuTLS step 1...\n");
1005 ret = IPHONE_E_SUCCESS; 943 gnutls_transport_set_ptr(*client->ssl_session, (gnutls_transport_ptr_t) client);
1006 } 944 log_dbg_msg(DBGMASK_LOCKDOWND, "GnuTLS step 2...\n");
945 gnutls_transport_set_push_function(*client->ssl_session, (gnutls_push_func) & lockdownd_secuwrite);
946 log_dbg_msg(DBGMASK_LOCKDOWND, "GnuTLS step 3...\n");
947 gnutls_transport_set_pull_function(*client->ssl_session, (gnutls_pull_func) & lockdownd_securead);
948 log_dbg_msg(DBGMASK_LOCKDOWND, "GnuTLS step 4 -- now handshaking...\n");
949
950 if (errno)
951 log_dbg_msg(DBGMASK_LOCKDOWND, "WARN: errno says %s before handshake!\n", strerror(errno));
952 return_me = gnutls_handshake(*client->ssl_session);
953 log_dbg_msg(DBGMASK_LOCKDOWND, "GnuTLS handshake done...\n");
954
955 if (return_me != GNUTLS_E_SUCCESS) {
956 log_dbg_msg(DBGMASK_LOCKDOWND, "GnuTLS reported something wrong.\n");
957 gnutls_perror(return_me);
958 log_dbg_msg(DBGMASK_LOCKDOWND, "oh.. errno says %s\n", strerror(errno));
959 return IPHONE_E_SSL_ERROR;
960 } else {
961 client->in_SSL = 1;
962 ret = IPHONE_E_SUCCESS;
1007 } 963 }
1008 } 964 }
1009 //store session id 965 //store session id
@@ -1020,10 +976,11 @@ iphone_error_t lockdownd_start_SSL_session(iphone_lckd_client_t control, const c
1020 976
1021 if (session_node_val_type == PLIST_STRING && session_id) { 977 if (session_node_val_type == PLIST_STRING && session_id) {
1022 // we need to store the session ID for StopSession 978 // we need to store the session ID for StopSession
1023 strcpy(control->session_id, session_id); 979 strcpy(client->session_id, session_id);
1024 log_dbg_msg(DBGMASK_LOCKDOWND, "SessionID: %s\n", control->session_id); 980 log_dbg_msg(DBGMASK_LOCKDOWND, "SessionID: %s\n", client->session_id);
1025 } 981 }
1026 free(session_id); 982 if (session_id)
983 free(session_id);
1027 } 984 }
1028 } else 985 } else
1029 log_dbg_msg(DBGMASK_LOCKDOWND, "Failed to get SessionID!\n"); 986 log_dbg_msg(DBGMASK_LOCKDOWND, "Failed to get SessionID!\n");
@@ -1048,11 +1005,11 @@ iphone_error_t lockdownd_start_SSL_session(iphone_lckd_client_t control, const c
1048ssize_t lockdownd_secuwrite(gnutls_transport_ptr_t transport, char *buffer, size_t length) 1005ssize_t lockdownd_secuwrite(gnutls_transport_ptr_t transport, char *buffer, size_t length)
1049{ 1006{
1050 uint32_t bytes = 0; 1007 uint32_t bytes = 0;
1051 iphone_lckd_client_t control; 1008 lockdownd_client_t client;
1052 control = (iphone_lckd_client_t) transport; 1009 client = (lockdownd_client_t) transport;
1053 log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_secuwrite() called\n"); 1010 log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_secuwrite() called\n");
1054 log_dbg_msg(DBGMASK_LOCKDOWND, "pre-send\nlength = %zi\n", length); 1011 log_dbg_msg(DBGMASK_LOCKDOWND, "pre-send\nlength = %zi\n", length);
1055 usbmuxd_send(control->sfd, buffer, length, &bytes); 1012 usbmuxd_send(client->sfd, buffer, length, &bytes);
1056 log_dbg_msg(DBGMASK_LOCKDOWND, "post-send\nsent %i bytes\n", bytes); 1013 log_dbg_msg(DBGMASK_LOCKDOWND, "post-send\nsent %i bytes\n", bytes);
1057 1014
1058 dump_debug_buffer("sslpacketwrite.out", buffer, length); 1015 dump_debug_buffer("sslpacketwrite.out", buffer, length);
@@ -1073,8 +1030,8 @@ ssize_t lockdownd_securead(gnutls_transport_ptr_t transport, char *buffer, size_
1073 size_t tbytes = 0; 1030 size_t tbytes = 0;
1074 int this_len = length; 1031 int this_len = length;
1075 iphone_error_t res; 1032 iphone_error_t res;
1076 iphone_lckd_client_t control; 1033 lockdownd_client_t client;
1077 control = (iphone_lckd_client_t) transport; 1034 client = (lockdownd_client_t) transport;
1078 char *recv_buffer; 1035 char *recv_buffer;
1079 1036
1080 log_debug_msg("lockdownd_securead() called\nlength = %zi\n", length); 1037 log_debug_msg("lockdownd_securead() called\nlength = %zi\n", length);
@@ -1085,8 +1042,8 @@ ssize_t lockdownd_securead(gnutls_transport_ptr_t transport, char *buffer, size_
1085 1042
1086 // repeat until we have the full data or an error occurs. 1043 // repeat until we have the full data or an error occurs.
1087 do { 1044 do {
1088 if ((res = usbmuxd_recv(control->sfd, recv_buffer, this_len, (uint32_t*)&bytes)) != IPHONE_E_SUCCESS) { 1045 if ((res = usbmuxd_recv(client->sfd, recv_buffer, this_len, (uint32_t*)&bytes)) != IPHONE_E_SUCCESS) {
1089 log_debug_msg("%s: ERROR: iphone_mux_recv returned %d\n", __func__, res); 1046 log_debug_msg("%s: ERROR: usbmux_recv returned %d\n", __func__, res);
1090 return res; 1047 return res;
1091 } 1048 }
1092 log_debug_msg("post-read\nwe got %i bytes\n", bytes); 1049 log_debug_msg("post-read\nwe got %i bytes\n", bytes);
@@ -1105,6 +1062,7 @@ ssize_t lockdownd_securead(gnutls_transport_ptr_t transport, char *buffer, size_
1105 this_len = length - tbytes; 1062 this_len = length - tbytes;
1106 log_debug_msg("re-read\ntrying to read missing %i bytes\n", this_len); 1063 log_debug_msg("re-read\ntrying to read missing %i bytes\n", this_len);
1107 } while (tbytes < length); 1064 } while (tbytes < length);
1065
1108 if (recv_buffer) { 1066 if (recv_buffer) {
1109 free(recv_buffer); 1067 free(recv_buffer);
1110 } 1068 }
@@ -1114,13 +1072,13 @@ ssize_t lockdownd_securead(gnutls_transport_ptr_t transport, char *buffer, size_
1114 1072
1115/** Command to start the desired service 1073/** Command to start the desired service
1116 * 1074 *
1117 * @param control The lockdownd client 1075 * @param client The lockdownd client
1118 * @param service The name of the service to start 1076 * @param service The name of the service to start
1119 * @param port The port number the service was started on 1077 * @param port The port number the service was started on
1120 1078
1121 * @return an error code 1079 * @return an error code (IPHONE_E_SUCCESS on success)
1122 */ 1080 */
1123iphone_error_t iphone_lckd_start_service(iphone_lckd_client_t client, const char *service, int *port) 1081iphone_error_t lockdownd_start_service(lockdownd_client_t client, const char *service, int *port)
1124{ 1082{
1125 if (!client || !service || !port) 1083 if (!client || !service || !port)
1126 return IPHONE_E_INVALID_ARG; 1084 return IPHONE_E_INVALID_ARG;
@@ -1128,7 +1086,7 @@ iphone_error_t iphone_lckd_start_service(iphone_lckd_client_t client, const char
1128 char *host_id = get_host_id(); 1086 char *host_id = get_host_id();
1129 if (!host_id) 1087 if (!host_id)
1130 return IPHONE_E_INVALID_CONF; 1088 return IPHONE_E_INVALID_CONF;
1131 if (!client->in_SSL && !lockdownd_start_SSL_session(client, host_id)) 1089 if (!client->in_SSL && !lockdownd_start_ssl_session(client, host_id))
1132 return IPHONE_E_SSL_ERROR; 1090 return IPHONE_E_SSL_ERROR;
1133 1091
1134 plist_t dict = NULL; 1092 plist_t dict = NULL;
@@ -1145,14 +1103,14 @@ iphone_error_t iphone_lckd_start_service(iphone_lckd_client_t client, const char
1145 plist_add_sub_string_el(dict, service); 1103 plist_add_sub_string_el(dict, service);
1146 1104
1147 /* send to iPhone */ 1105 /* send to iPhone */
1148 ret = iphone_lckd_send(client, dict); 1106 ret = lockdownd_send(client, dict);
1149 plist_free(dict); 1107 plist_free(dict);
1150 dict = NULL; 1108 dict = NULL;
1151 1109
1152 if (IPHONE_E_SUCCESS != ret) 1110 if (IPHONE_E_SUCCESS != ret)
1153 return ret; 1111 return ret;
1154 1112
1155 ret = iphone_lckd_recv(client, &dict); 1113 ret = lockdownd_recv(client, &dict);
1156 1114
1157 if (IPHONE_E_SUCCESS != ret) 1115 if (IPHONE_E_SUCCESS != ret)
1158 return ret; 1116 return ret;
@@ -1161,47 +1119,33 @@ iphone_error_t iphone_lckd_start_service(iphone_lckd_client_t client, const char
1161 return IPHONE_E_PLIST_ERROR; 1119 return IPHONE_E_PLIST_ERROR;
1162 1120
1163 ret = IPHONE_E_UNKNOWN_ERROR; 1121 ret = IPHONE_E_UNKNOWN_ERROR;
1164 1122 if (lockdown_check_result(dict, "StartService") == RESULT_SUCCESS) {
1165 plist_t query_node = plist_find_node_by_string(dict, "StartService"); 1123 plist_t port_key_node = plist_find_node_by_key(dict, "Port");
1166 plist_t result_key_node = plist_get_next_sibling(query_node); 1124 plist_t port_value_node = plist_get_next_sibling(port_key_node);
1167 plist_t result_value_node = plist_get_next_sibling(result_key_node); 1125
1168 1126 if ((plist_get_node_type(port_key_node) == PLIST_KEY)
1169 plist_t port_key_node = plist_find_node_by_key(dict, "Port"); 1127 && (plist_get_node_type(port_value_node) == PLIST_UINT)) {
1170 plist_t port_value_node = plist_get_next_sibling(port_key_node); 1128 char *port_key = NULL;
1171 1129 uint64_t port_value = 0;
1172 plist_type result_key_type = plist_get_node_type(result_key_node); 1130
1173 plist_type result_value_type = plist_get_node_type(result_value_node); 1131 plist_get_key_val(port_key_node, &port_key);
1174 plist_type port_key_type = plist_get_node_type(port_key_node); 1132 plist_get_uint_val(port_value_node, &port_value);
1175 plist_type port_value_type = plist_get_node_type(port_value_node); 1133 if (port_key && !strcmp(port_key, "Port")) {
1176 1134 port_loc = port_value;
1177 if (result_key_type == PLIST_KEY && result_value_type == PLIST_STRING) { 1135 ret = IPHONE_E_SUCCESS;
1178 char *result_key = NULL;
1179 char *result_value = NULL;
1180 char *port_key = NULL;
1181 uint64_t port_value = 0;
1182
1183 plist_get_key_val(result_key_node, &result_key);
1184 plist_get_string_val(result_value_node, &result_value);
1185
1186 if (!strcmp(result_key, "Result") && !strcmp(result_value, "Failure")) {
1187 ret = IPHONE_E_START_SERVICE_FAILED;
1188 } else {
1189 if (port_key_type == PLIST_KEY && port_value_type == PLIST_UINT) {
1190 plist_get_key_val(port_key_node, &port_key);
1191 plist_get_uint_val(port_value_node, &port_value);
1192
1193 if (!strcmp(result_key, "Result") && !strcmp(result_value, "Success") && !strcmp(port_key, "Port")) {
1194 port_loc = port_value;
1195 ret = IPHONE_E_SUCCESS;
1196 }
1197
1198 if (port && ret == IPHONE_E_SUCCESS)
1199 *port = port_loc;
1200 } 1136 }
1137 if (port_key)
1138 free(port_key);
1139
1140 if (port && ret == IPHONE_E_SUCCESS)
1141 *port = port_loc;
1201 } 1142 }
1202 } 1143 }
1144 else
1145 ret = IPHONE_E_START_SERVICE_FAILED;
1203 1146
1204 plist_free(dict); 1147 plist_free(dict);
1205 dict = NULL; 1148 dict = NULL;
1206 return ret; 1149 return ret;
1207} 1150}
1151