diff options
Diffstat (limited to 'src/lockdown.c')
| -rw-r--r-- | src/lockdown.c | 89 |
1 files changed, 52 insertions, 37 deletions
diff --git a/src/lockdown.c b/src/lockdown.c index 5ade79a..ae408be 100644 --- a/src/lockdown.c +++ b/src/lockdown.c | |||
| @@ -19,7 +19,6 @@ | |||
| 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| 20 | */ | 20 | */ |
| 21 | 21 | ||
| 22 | #include "usbmux.h" | ||
| 23 | #include "utils.h" | 22 | #include "utils.h" |
| 24 | #include "iphone.h" | 23 | #include "iphone.h" |
| 25 | #include "lockdown.h" | 24 | #include "lockdown.h" |
| @@ -27,6 +26,7 @@ | |||
| 27 | #include <arpa/inet.h> | 26 | #include <arpa/inet.h> |
| 28 | #include <errno.h> | 27 | #include <errno.h> |
| 29 | #include <string.h> | 28 | #include <string.h> |
| 29 | #include <stdlib.h> | ||
| 30 | #include <glib.h> | 30 | #include <glib.h> |
| 31 | #include <libtasn1.h> | 31 | #include <libtasn1.h> |
| 32 | #include <gnutls/x509.h> | 32 | #include <gnutls/x509.h> |
| @@ -53,13 +53,15 @@ iphone_lckd_client_t new_lockdownd_client(iphone_device_t phone) | |||
| 53 | { | 53 | { |
| 54 | if (!phone) | 54 | if (!phone) |
| 55 | return NULL; | 55 | return NULL; |
| 56 | iphone_lckd_client_t control = (iphone_lckd_client_t) malloc(sizeof(struct iphone_lckd_client_int)); | ||
| 57 | 56 | ||
| 58 | if (IPHONE_E_SUCCESS != iphone_mux_new_client(phone, 0x0a00, 0xf27e, &control->connection)) { | 57 | int sfd = usbmuxd_connect(phone->handle, 0xf27e); |
| 59 | free(control); | 58 | if (sfd < 0) { |
| 59 | log_debug_msg("%s: could not connect to lockdownd (device handle %d)\n", __func__, phone->handle); | ||
| 60 | return NULL; | 60 | return NULL; |
| 61 | } | 61 | } |
| 62 | 62 | ||
| 63 | iphone_lckd_client_t control = (iphone_lckd_client_t) malloc(sizeof(struct iphone_lckd_client_int)); | ||
| 64 | control->sfd = sfd; | ||
| 63 | control->ssl_session = (gnutls_session_t *) malloc(sizeof(gnutls_session_t)); | 65 | control->ssl_session = (gnutls_session_t *) malloc(sizeof(gnutls_session_t)); |
| 64 | control->in_SSL = 0; | 66 | control->in_SSL = 0; |
| 65 | return control; | 67 | return control; |
| @@ -167,13 +169,13 @@ iphone_error_t iphone_lckd_free_client(iphone_lckd_client_t client) | |||
| 167 | 169 | ||
| 168 | iphone_lckd_stop_SSL_session(client); | 170 | iphone_lckd_stop_SSL_session(client); |
| 169 | 171 | ||
| 170 | if (client->connection) { | 172 | if (client->sfd > 0) { |
| 171 | lockdownd_close(client); | 173 | lockdownd_close(client); |
| 172 | 174 | ||
| 173 | // IMO, read of final "sessionUpcall connection closed" packet | 175 | // IMO, read of final "sessionUpcall connection closed" packet |
| 174 | // should come here instead of in iphone_free_device | 176 | // should come here instead of in iphone_free_device |
| 175 | 177 | ||
| 176 | ret = iphone_mux_free_client(client->connection); | 178 | ret = usbmuxd_disconnect(client->sfd); |
| 177 | } | 179 | } |
| 178 | 180 | ||
| 179 | free(client); | 181 | free(client); |
| @@ -197,11 +199,16 @@ iphone_error_t iphone_lckd_recv(iphone_lckd_client_t client, plist_t * plist) | |||
| 197 | uint32_t datalen = 0, bytes = 0, received_bytes = 0; | 199 | uint32_t datalen = 0, bytes = 0, received_bytes = 0; |
| 198 | 200 | ||
| 199 | if (!client->in_SSL) | 201 | if (!client->in_SSL) |
| 200 | ret = iphone_mux_recv(client->connection, (char *) &datalen, sizeof(datalen), &bytes); | 202 | ret = usbmuxd_recv(client->sfd, (char *) &datalen, sizeof(datalen), &bytes); |
| 201 | else { | 203 | else { |
| 202 | bytes = gnutls_record_recv(*client->ssl_session, &datalen, sizeof(datalen)); | 204 | ssize_t res = gnutls_record_recv(*client->ssl_session, &datalen, sizeof(datalen)); |
| 203 | if (bytes > 0) | 205 | if (res < 0) { |
| 206 | log_dbg_msg(DBGMASK_LOCKDOWND, "gnutls_record_recv: Error occured: %s\n", gnutls_strerror(res)); | ||
| 207 | return IPHONE_E_SSL_ERROR; | ||
| 208 | } else { | ||
| 209 | bytes = res; | ||
| 204 | ret = IPHONE_E_SUCCESS; | 210 | ret = IPHONE_E_SUCCESS; |
| 211 | } | ||
| 205 | } | 212 | } |
| 206 | datalen = ntohl(datalen); | 213 | datalen = ntohl(datalen); |
| 207 | 214 | ||
| @@ -210,13 +217,18 @@ iphone_error_t iphone_lckd_recv(iphone_lckd_client_t client, plist_t * plist) | |||
| 210 | if (!client->in_SSL) { | 217 | if (!client->in_SSL) { |
| 211 | /* fill buffer and request more packets if needed */ | 218 | /* fill buffer and request more packets if needed */ |
| 212 | while ((received_bytes < datalen) && (ret == IPHONE_E_SUCCESS)) { | 219 | while ((received_bytes < datalen) && (ret == IPHONE_E_SUCCESS)) { |
| 213 | ret = iphone_mux_recv(client->connection, receive + received_bytes, datalen - received_bytes, &bytes); | 220 | ret = usbmuxd_recv(client->sfd, receive + received_bytes, datalen - received_bytes, &bytes); |
| 214 | received_bytes += bytes; | 221 | received_bytes += bytes; |
| 215 | } | 222 | } |
| 216 | } else { | 223 | } else { |
| 217 | received_bytes = gnutls_record_recv(*client->ssl_session, receive, datalen); | 224 | ssize_t res = gnutls_record_recv(*client->ssl_session, receive, datalen); |
| 218 | if (received_bytes > 0) | 225 | if (res < 0) { |
| 226 | log_dbg_msg(DBGMASK_LOCKDOWND, "gnutls_record_recv: Error occured: %s\n", gnutls_strerror(res)); | ||
| 227 | ret = IPHONE_E_SSL_ERROR; | ||
| 228 | } else { | ||
| 229 | received_bytes = res; | ||
| 219 | ret = IPHONE_E_SUCCESS; | 230 | ret = IPHONE_E_SUCCESS; |
| 231 | } | ||
| 220 | } | 232 | } |
| 221 | 233 | ||
| 222 | if (ret != IPHONE_E_SUCCESS) { | 234 | if (ret != IPHONE_E_SUCCESS) { |
| @@ -224,7 +236,7 @@ iphone_error_t iphone_lckd_recv(iphone_lckd_client_t client, plist_t * plist) | |||
| 224 | return ret; | 236 | return ret; |
| 225 | } | 237 | } |
| 226 | 238 | ||
| 227 | if (received_bytes <= 0) { | 239 | if ((ssize_t)received_bytes <= 0) { |
| 228 | free(receive); | 240 | free(receive); |
| 229 | return IPHONE_E_NOT_ENOUGH_DATA; | 241 | return IPHONE_E_NOT_ENOUGH_DATA; |
| 230 | } | 242 | } |
| @@ -271,12 +283,22 @@ iphone_error_t iphone_lckd_send(iphone_lckd_client_t client, plist_t plist) | |||
| 271 | log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_send(): made the query, sending it along\n"); | 283 | log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_send(): made the query, sending it along\n"); |
| 272 | 284 | ||
| 273 | if (!client->in_SSL) | 285 | if (!client->in_SSL) |
| 274 | ret = iphone_mux_send(client->connection, real_query, ntohl(length) + sizeof(length), &bytes); | 286 | ret = usbmuxd_send(client->sfd, real_query, ntohl(length) + sizeof(length), (uint32_t*)&bytes); |
| 275 | else { | 287 | else { |
| 276 | gnutls_record_send(*client->ssl_session, real_query, ntohl(length) + sizeof(length)); | 288 | ssize_t res = gnutls_record_send(*client->ssl_session, real_query, ntohl(length) + sizeof(length)); |
| 277 | ret = IPHONE_E_SUCCESS; | 289 | if (res < 0) { |
| 290 | log_dbg_msg(DBGMASK_LOCKDOWND, "gnutls_record_send: Error occured: %s\n", gnutls_strerror(res)); | ||
| 291 | ret = IPHONE_E_SSL_ERROR; | ||
| 292 | } else { | ||
| 293 | bytes = res; | ||
| 294 | ret = IPHONE_E_SUCCESS; | ||
| 295 | } | ||
| 296 | } | ||
| 297 | if (ret == IPHONE_E_SUCCESS) { | ||
| 298 | log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_send(): sent it!\n"); | ||
| 299 | } else { | ||
| 300 | log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_send(): sending failed!\n"); | ||
| 278 | } | 301 | } |
| 279 | log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_send(): sent it!\n"); | ||
| 280 | free(real_query); | 302 | free(real_query); |
| 281 | 303 | ||
| 282 | return ret; | 304 | return ret; |
| @@ -425,7 +447,7 @@ iphone_error_t lockdownd_generic_get_value(iphone_lckd_client_t control, const c | |||
| 425 | char *value_value = NULL; | 447 | char *value_value = NULL; |
| 426 | plist_get_string_val(value_value_node, &value_value); | 448 | plist_get_string_val(value_value_node, &value_value); |
| 427 | 449 | ||
| 428 | value->data = value_value; | 450 | value->data = (unsigned char*)value_value; |
| 429 | value->size = strlen(value_value); | 451 | value->size = strlen(value_value); |
| 430 | ret = IPHONE_E_SUCCESS; | 452 | ret = IPHONE_E_SUCCESS; |
| 431 | } | 453 | } |
| @@ -435,7 +457,7 @@ iphone_error_t lockdownd_generic_get_value(iphone_lckd_client_t control, const c | |||
| 435 | uint64_t size = 0; | 457 | uint64_t size = 0; |
| 436 | plist_get_data_val(value_value_node, &value_value, &size); | 458 | plist_get_data_val(value_value_node, &value_value, &size); |
| 437 | 459 | ||
| 438 | value->data = value_value; | 460 | value->data = (unsigned char*)value_value; |
| 439 | value->size = size; | 461 | value->size = size; |
| 440 | ret = IPHONE_E_SUCCESS; | 462 | ret = IPHONE_E_SUCCESS; |
| 441 | } | 463 | } |
| @@ -457,7 +479,7 @@ iphone_error_t lockdownd_get_device_uid(iphone_lckd_client_t control, char **uid | |||
| 457 | { | 479 | { |
| 458 | gnutls_datum_t temp = { NULL, 0 }; | 480 | gnutls_datum_t temp = { NULL, 0 }; |
| 459 | iphone_error_t ret = lockdownd_generic_get_value(control, "Key", "UniqueDeviceID", &temp); | 481 | iphone_error_t ret = lockdownd_generic_get_value(control, "Key", "UniqueDeviceID", &temp); |
| 460 | *uid = temp.data; | 482 | *uid = (char*)temp.data; |
| 461 | return ret; | 483 | return ret; |
| 462 | } | 484 | } |
| 463 | 485 | ||
| @@ -465,7 +487,7 @@ iphone_error_t lockdownd_get_device_uid(iphone_lckd_client_t control, char **uid | |||
| 465 | * | 487 | * |
| 466 | * @note You most likely want lockdownd_init unless you are doing something special. | 488 | * @note You most likely want lockdownd_init unless you are doing something special. |
| 467 | * | 489 | * |
| 468 | * @return 1 on success and 0 on failure. | 490 | * @return IPHONE_E_SUCCESS on succes or an error value < 0 on failure. |
| 469 | */ | 491 | */ |
| 470 | iphone_error_t lockdownd_get_device_public_key(iphone_lckd_client_t control, gnutls_datum_t * public_key) | 492 | iphone_error_t lockdownd_get_device_public_key(iphone_lckd_client_t control, gnutls_datum_t * public_key) |
| 471 | { | 493 | { |
| @@ -733,14 +755,14 @@ iphone_error_t lockdownd_gen_pair_cert(gnutls_datum_t public_key, gnutls_datum_t | |||
| 733 | if (ASN1_SUCCESS == asn1_der_decoding(&asn1_pub_key, der_pub_key.data, der_pub_key.size, NULL)) { | 755 | if (ASN1_SUCCESS == asn1_der_decoding(&asn1_pub_key, der_pub_key.data, der_pub_key.size, NULL)) { |
| 734 | 756 | ||
| 735 | /* get size to read */ | 757 | /* get size to read */ |
| 736 | int ret1 = asn1_read_value(asn1_pub_key, "modulus", NULL, &modulus.size); | 758 | int ret1 = asn1_read_value(asn1_pub_key, "modulus", NULL, (int*)&modulus.size); |
| 737 | int ret2 = asn1_read_value(asn1_pub_key, "publicExponent", NULL, &exponent.size); | 759 | int ret2 = asn1_read_value(asn1_pub_key, "publicExponent", NULL, (int*)&exponent.size); |
| 738 | 760 | ||
| 739 | modulus.data = gnutls_malloc(modulus.size); | 761 | modulus.data = gnutls_malloc(modulus.size); |
| 740 | exponent.data = gnutls_malloc(exponent.size); | 762 | exponent.data = gnutls_malloc(exponent.size); |
| 741 | 763 | ||
| 742 | ret1 = asn1_read_value(asn1_pub_key, "modulus", modulus.data, &modulus.size); | 764 | ret1 = asn1_read_value(asn1_pub_key, "modulus", modulus.data, (int*)&modulus.size); |
| 743 | ret2 = asn1_read_value(asn1_pub_key, "publicExponent", exponent.data, &exponent.size); | 765 | ret2 = asn1_read_value(asn1_pub_key, "publicExponent", exponent.data, (int*)&exponent.size); |
| 744 | if (ASN1_SUCCESS == ret1 && ASN1_SUCCESS == ret2) | 766 | if (ASN1_SUCCESS == ret1 && ASN1_SUCCESS == ret2) |
| 745 | ret = IPHONE_E_SUCCESS; | 767 | ret = IPHONE_E_SUCCESS; |
| 746 | } | 768 | } |
| @@ -755,7 +777,7 @@ iphone_error_t lockdownd_gen_pair_cert(gnutls_datum_t public_key, gnutls_datum_t | |||
| 755 | if (IPHONE_E_SUCCESS == ret && 0 != modulus.size && 0 != exponent.size) { | 777 | if (IPHONE_E_SUCCESS == ret && 0 != modulus.size && 0 != exponent.size) { |
| 756 | 778 | ||
| 757 | gnutls_global_init(); | 779 | gnutls_global_init(); |
| 758 | gnutls_datum_t essentially_null = { strdup("abababababababab"), strlen("abababababababab") }; | 780 | gnutls_datum_t essentially_null = { (unsigned char*)strdup("abababababababab"), strlen("abababababababab") }; |
| 759 | 781 | ||
| 760 | gnutls_x509_privkey_t fake_privkey, root_privkey, host_privkey; | 782 | gnutls_x509_privkey_t fake_privkey, root_privkey, host_privkey; |
| 761 | gnutls_x509_crt_t dev_cert, root_cert, host_cert; | 783 | gnutls_x509_crt_t dev_cert, root_cert, host_cert; |
| @@ -1021,12 +1043,12 @@ iphone_error_t lockdownd_start_SSL_session(iphone_lckd_client_t control, const c | |||
| 1021 | */ | 1043 | */ |
| 1022 | ssize_t lockdownd_secuwrite(gnutls_transport_ptr_t transport, char *buffer, size_t length) | 1044 | ssize_t lockdownd_secuwrite(gnutls_transport_ptr_t transport, char *buffer, size_t length) |
| 1023 | { | 1045 | { |
| 1024 | int bytes = 0; | 1046 | uint32_t bytes = 0; |
| 1025 | iphone_lckd_client_t control; | 1047 | iphone_lckd_client_t control; |
| 1026 | control = (iphone_lckd_client_t) transport; | 1048 | control = (iphone_lckd_client_t) transport; |
| 1027 | log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_secuwrite() called\n"); | 1049 | log_dbg_msg(DBGMASK_LOCKDOWND, "lockdownd_secuwrite() called\n"); |
| 1028 | log_dbg_msg(DBGMASK_LOCKDOWND, "pre-send\nlength = %zi\n", length); | 1050 | log_dbg_msg(DBGMASK_LOCKDOWND, "pre-send\nlength = %zi\n", length); |
| 1029 | iphone_mux_send(control->connection, buffer, length, &bytes); | 1051 | usbmuxd_send(control->sfd, buffer, length, &bytes); |
| 1030 | log_dbg_msg(DBGMASK_LOCKDOWND, "post-send\nsent %i bytes\n", bytes); | 1052 | log_dbg_msg(DBGMASK_LOCKDOWND, "post-send\nsent %i bytes\n", bytes); |
| 1031 | 1053 | ||
| 1032 | dump_debug_buffer("sslpacketwrite.out", buffer, length); | 1054 | dump_debug_buffer("sslpacketwrite.out", buffer, length); |
| @@ -1044,7 +1066,7 @@ ssize_t lockdownd_secuwrite(gnutls_transport_ptr_t transport, char *buffer, size | |||
| 1044 | ssize_t lockdownd_securead(gnutls_transport_ptr_t transport, char *buffer, size_t length) | 1066 | ssize_t lockdownd_securead(gnutls_transport_ptr_t transport, char *buffer, size_t length) |
| 1045 | { | 1067 | { |
| 1046 | int bytes = 0, pos_start_fill = 0; | 1068 | int bytes = 0, pos_start_fill = 0; |
| 1047 | int tbytes = 0; | 1069 | size_t tbytes = 0; |
| 1048 | int this_len = length; | 1070 | int this_len = length; |
| 1049 | iphone_error_t res; | 1071 | iphone_error_t res; |
| 1050 | iphone_lckd_client_t control; | 1072 | iphone_lckd_client_t control; |
| @@ -1059,19 +1081,12 @@ ssize_t lockdownd_securead(gnutls_transport_ptr_t transport, char *buffer, size_ | |||
| 1059 | 1081 | ||
| 1060 | // repeat until we have the full data or an error occurs. | 1082 | // repeat until we have the full data or an error occurs. |
| 1061 | do { | 1083 | do { |
| 1062 | if ((res = iphone_mux_recv(control->connection, recv_buffer, this_len, &bytes)) != IPHONE_E_SUCCESS) { | 1084 | if ((res = usbmuxd_recv(control->sfd, recv_buffer, this_len, (uint32_t*)&bytes)) != IPHONE_E_SUCCESS) { |
| 1063 | log_debug_msg("%s: ERROR: iphone_mux_recv returned %d\n", __func__, res); | 1085 | log_debug_msg("%s: ERROR: iphone_mux_recv returned %d\n", __func__, res); |
| 1064 | return res; | 1086 | return res; |
| 1065 | } | 1087 | } |
| 1066 | log_debug_msg("post-read\nwe got %i bytes\n", bytes); | 1088 | log_debug_msg("post-read\nwe got %i bytes\n", bytes); |
| 1067 | 1089 | ||
| 1068 | if (bytes < 0) { | ||
| 1069 | log_debug_msg("lockdownd_securead(): uh oh\n"); | ||
| 1070 | log_debug_msg | ||
| 1071 | ("I believe what we have here is a failure to communicate... libusb says %s but strerror says %s\n", | ||
| 1072 | usb_strerror(), strerror(errno)); | ||
| 1073 | return bytes; // + 28; // an errno | ||
| 1074 | } | ||
| 1075 | // increase read count | 1090 | // increase read count |
| 1076 | tbytes += bytes; | 1091 | tbytes += bytes; |
| 1077 | 1092 | ||
