diff options
| -rw-r--r-- | include/libiphone/libiphone.h | 1 | ||||
| -rw-r--r-- | src/InstallationProxy.c | 138 | ||||
| -rw-r--r-- | src/MobileSync.c | 69 | ||||
| -rw-r--r-- | src/NotificationProxy.c | 162 | ||||
| -rw-r--r-- | src/SBServices.c | 155 | ||||
| -rw-r--r-- | src/iphone.c | 281 | ||||
| -rw-r--r-- | src/iphone.h | 13 | ||||
| -rw-r--r-- | src/lockdown.c | 98 |
8 files changed, 453 insertions, 464 deletions
diff --git a/include/libiphone/libiphone.h b/include/libiphone/libiphone.h index 923bc58..eb58d5c 100644 --- a/include/libiphone/libiphone.h +++ b/include/libiphone/libiphone.h | |||
| @@ -39,6 +39,7 @@ extern "C" { | |||
| 39 | #define IPHONE_E_NO_DEVICE -3 | 39 | #define IPHONE_E_NO_DEVICE -3 |
| 40 | #define IPHONE_E_NOT_ENOUGH_DATA -4 | 40 | #define IPHONE_E_NOT_ENOUGH_DATA -4 |
| 41 | #define IPHONE_E_BAD_HEADER -5 | 41 | #define IPHONE_E_BAD_HEADER -5 |
| 42 | #define IPHONE_E_PLIST_ERROR -6 | ||
| 42 | 43 | ||
| 43 | typedef int16_t iphone_error_t; | 44 | typedef int16_t iphone_error_t; |
| 44 | 45 | ||
diff --git a/src/InstallationProxy.c b/src/InstallationProxy.c index 917886d..387f9ca 100644 --- a/src/InstallationProxy.c +++ b/src/InstallationProxy.c | |||
| @@ -56,112 +56,28 @@ static void instproxy_unlock(instproxy_client_t client) | |||
| 56 | } | 56 | } |
| 57 | 57 | ||
| 58 | /** | 58 | /** |
| 59 | * Sends an xml plist to the device using the connection specified in client. | 59 | * Convert an iphone_error_t value to an instproxy_error_t value. |
| 60 | * This function is only used internally. | 60 | * Used internally to get correct error codes when using plist helper |
| 61 | * functions. | ||
| 61 | * | 62 | * |
| 62 | * @param client The installation_proxy to send data to | 63 | * @param err An iphone_error_t error code |
| 63 | * @param plist plist to send | ||
| 64 | * | 64 | * |
| 65 | * @return INSTPROXY_E_SUCCESS on success, INSTPROXY_E_INVALID_ARG when client | 65 | * @return A matching instproxy_error_t error code, |
| 66 | * or plist are NULL, INSTPROXY_E_PLIST_ERROR when dict is not a valid | 66 | * INSTPROXY_E_UNKNOWN_ERROR otherwise. |
| 67 | * plist, or INSTPROXY_E_UNKNOWN_ERROR when an unspecified error occurs. | ||
| 68 | */ | 67 | */ |
| 69 | static instproxy_error_t instproxy_plist_send(instproxy_client_t client, plist_t plist) | 68 | static instproxy_error_t iphone_to_instproxy_error(iphone_error_t err) |
| 70 | { | 69 | { |
| 71 | instproxy_error_t res = INSTPROXY_E_UNKNOWN_ERROR; | 70 | switch (err) { |
| 72 | char *XML_content = NULL; | 71 | case IPHONE_E_SUCCESS: |
| 73 | uint32_t length = 0; | 72 | return INSTPROXY_E_SUCCESS; |
| 74 | uint32_t nlen = 0; | 73 | case IPHONE_E_INVALID_ARG: |
| 75 | int bytes = 0; | 74 | return INSTPROXY_E_INVALID_ARG; |
| 76 | 75 | case IPHONE_E_PLIST_ERROR: | |
| 77 | if (!client || !plist) { | 76 | return INSTPROXY_E_PLIST_ERROR; |
| 78 | return INSTPROXY_E_INVALID_ARG; | 77 | default: |
| 79 | } | 78 | break; |
| 80 | |||
| 81 | plist_to_xml(plist, &XML_content, &length); | ||
| 82 | |||
| 83 | if (!XML_content || length == 0) { | ||
| 84 | return INSTPROXY_E_PLIST_ERROR; | ||
| 85 | } | ||
| 86 | |||
| 87 | nlen = htonl(length); | ||
| 88 | log_debug_msg("%s: sending %d bytes\n", __func__, length); | ||
| 89 | iphone_device_send(client->connection, (const char*)&nlen, sizeof(nlen), (uint32_t*)&bytes); | ||
| 90 | if (bytes == sizeof(nlen)) { | ||
| 91 | iphone_device_send(client->connection, XML_content, length, (uint32_t*)&bytes); | ||
| 92 | if (bytes > 0) { | ||
| 93 | log_debug_msg("%s: received %d bytes\n", __func__, bytes); | ||
| 94 | log_debug_buffer(XML_content, bytes); | ||
| 95 | if ((uint32_t)bytes == length) { | ||
| 96 | res = INSTPROXY_E_SUCCESS; | ||
| 97 | } else { | ||
| 98 | log_debug_msg("%s: ERROR: Could not send all data (%d of %d)!\n", __func__, bytes, length); | ||
| 99 | } | ||
| 100 | } | ||
| 101 | } | ||
| 102 | if (bytes <= 0) { | ||
| 103 | log_dbg_msg(DBGMASK_INSTPROXY, "%s: ERROR: sending to device failed.\n", __func__); | ||
| 104 | } | ||
| 105 | |||
| 106 | free(XML_content); | ||
| 107 | |||
| 108 | return res; | ||
| 109 | } | ||
| 110 | |||
| 111 | /** | ||
| 112 | * Receives an xml plist from the device using the connection specified in | ||
| 113 | * client. | ||
| 114 | * This function is only used internally. | ||
| 115 | * | ||
| 116 | * @param client The installation_proxy to receive data from | ||
| 117 | * @param plist pointer to a plist_t that will point to the received plist | ||
| 118 | * upon successful return | ||
| 119 | * | ||
| 120 | * @return INSTPROXY_E_SUCCESS on success, INSTPROXY_E_INVALID_ARG when client | ||
| 121 | * or *plist are NULL, INSTPROXY_E_PLIST_ERROR when dict is not a valid | ||
| 122 | * plist, or INSTPROXY_E_UNKNOWN_ERROR when an unspecified error occurs. | ||
| 123 | */ | ||
| 124 | static instproxy_error_t instproxy_plist_recv(instproxy_client_t client, plist_t *plist) | ||
| 125 | { | ||
| 126 | instproxy_error_t res = INSTPROXY_E_UNKNOWN_ERROR; | ||
| 127 | char *XML_content = NULL; | ||
| 128 | uint32_t pktlen = 0; | ||
| 129 | uint32_t bytes = 0; | ||
| 130 | |||
| 131 | if (!client || !plist) { | ||
| 132 | return INSTPROXY_E_INVALID_ARG; | ||
| 133 | } | ||
| 134 | |||
| 135 | iphone_device_recv_timeout(client->connection, (char*)&pktlen, sizeof(pktlen), &bytes, 300000); /* 5 minute timeout should be enough */ | ||
| 136 | log_debug_msg("%s: initial read=%i\n", __func__, bytes); | ||
| 137 | if (bytes < 4) { | ||
| 138 | log_dbg_msg(DBGMASK_INSTPROXY, "%s: initial read failed!\n"); | ||
| 139 | } else { | ||
| 140 | if ((char)pktlen == 0) { | ||
| 141 | uint32_t curlen = 0; | ||
| 142 | pktlen = ntohl(pktlen); | ||
| 143 | log_debug_msg("%s: %d bytes following\n", __func__, pktlen); | ||
| 144 | XML_content = (char*)malloc(pktlen); | ||
| 145 | |||
| 146 | while (curlen < pktlen) { | ||
| 147 | iphone_device_recv(client->connection, XML_content+curlen, pktlen-curlen, &bytes); | ||
| 148 | if (bytes <= 0) { | ||
| 149 | res = INSTPROXY_E_UNKNOWN_ERROR; | ||
| 150 | break; | ||
| 151 | } | ||
| 152 | log_debug_msg("%s: received %d bytes\n", __func__, bytes); | ||
| 153 | curlen += bytes; | ||
| 154 | } | ||
| 155 | log_debug_buffer(XML_content, pktlen); | ||
| 156 | plist_from_xml(XML_content, pktlen, plist); | ||
| 157 | res = INSTPROXY_E_SUCCESS; | ||
| 158 | free(XML_content); | ||
| 159 | XML_content = NULL; | ||
| 160 | } else { | ||
| 161 | res = INSTPROXY_E_UNKNOWN_ERROR; | ||
| 162 | } | ||
| 163 | } | 79 | } |
| 164 | return res; | 80 | return INSTPROXY_E_UNKNOWN_ERROR; |
| 165 | } | 81 | } |
| 166 | 82 | ||
| 167 | /** | 83 | /** |
| @@ -268,7 +184,7 @@ instproxy_error_t instproxy_browse(instproxy_client_t client, instproxy_apptype_ | |||
| 268 | plist_dict_insert_item(dict, "Command", plist_new_string("Browse")); | 184 | plist_dict_insert_item(dict, "Command", plist_new_string("Browse")); |
| 269 | 185 | ||
| 270 | instproxy_lock(client); | 186 | instproxy_lock(client); |
| 271 | res = instproxy_plist_send(client, dict); | 187 | res = iphone_to_instproxy_error(iphone_device_send_xml_plist(client->connection, dict)); |
| 272 | plist_free(dict); | 188 | plist_free(dict); |
| 273 | if (res != INSTPROXY_E_SUCCESS) { | 189 | if (res != INSTPROXY_E_SUCCESS) { |
| 274 | log_dbg_msg(DBGMASK_INSTPROXY, "%s: could not send plist\n", __func__); | 190 | log_dbg_msg(DBGMASK_INSTPROXY, "%s: could not send plist\n", __func__); |
| @@ -280,7 +196,7 @@ instproxy_error_t instproxy_browse(instproxy_client_t client, instproxy_apptype_ | |||
| 280 | do { | 196 | do { |
| 281 | browsing = 0; | 197 | browsing = 0; |
| 282 | dict = NULL; | 198 | dict = NULL; |
| 283 | res = instproxy_plist_recv(client, &dict); | 199 | res = iphone_to_instproxy_error(iphone_device_receive_plist(client->connection, &dict)); |
| 284 | if (res != INSTPROXY_E_SUCCESS) { | 200 | if (res != INSTPROXY_E_SUCCESS) { |
| 285 | break; | 201 | break; |
| 286 | } | 202 | } |
| @@ -345,7 +261,7 @@ static instproxy_error_t instproxy_perform_operation(instproxy_client_t client, | |||
| 345 | 261 | ||
| 346 | do { | 262 | do { |
| 347 | instproxy_lock(client); | 263 | instproxy_lock(client); |
| 348 | res = instproxy_plist_recv(client, &dict); | 264 | res = iphone_to_instproxy_error(iphone_device_receive_plist_with_timeout(client->connection, &dict, 30000)); |
| 349 | instproxy_unlock(client); | 265 | instproxy_unlock(client); |
| 350 | if (res != INSTPROXY_E_SUCCESS) { | 266 | if (res != INSTPROXY_E_SUCCESS) { |
| 351 | log_dbg_msg(DBGMASK_INSTPROXY, "%s: could not receive plist, error %d\n", __func__, res); | 267 | log_dbg_msg(DBGMASK_INSTPROXY, "%s: could not receive plist, error %d\n", __func__, res); |
| @@ -517,7 +433,7 @@ static instproxy_error_t instproxy_install_or_upgrade(instproxy_client_t client, | |||
| 517 | plist_dict_insert_item(dict, "PackagePath", plist_new_string(pkg_path)); | 433 | plist_dict_insert_item(dict, "PackagePath", plist_new_string(pkg_path)); |
| 518 | 434 | ||
| 519 | instproxy_lock(client); | 435 | instproxy_lock(client); |
| 520 | res = instproxy_plist_send(client, dict); | 436 | res = iphone_to_instproxy_error(iphone_device_send_xml_plist(client->connection, dict)); |
| 521 | instproxy_unlock(client); | 437 | instproxy_unlock(client); |
| 522 | 438 | ||
| 523 | plist_free(dict); | 439 | plist_free(dict); |
| @@ -610,7 +526,7 @@ instproxy_error_t instproxy_uninstall(instproxy_client_t client, const char *app | |||
| 610 | plist_dict_insert_item(dict, "Command", plist_new_string("Uninstall")); | 526 | plist_dict_insert_item(dict, "Command", plist_new_string("Uninstall")); |
| 611 | 527 | ||
| 612 | instproxy_lock(client); | 528 | instproxy_lock(client); |
| 613 | res = instproxy_plist_send(client, dict); | 529 | res = iphone_to_instproxy_error(iphone_device_send_xml_plist(client->connection, dict)); |
| 614 | instproxy_unlock(client); | 530 | instproxy_unlock(client); |
| 615 | 531 | ||
| 616 | plist_free(dict); | 532 | plist_free(dict); |
| @@ -647,7 +563,7 @@ instproxy_error_t instproxy_lookup_archives(instproxy_client_t client, plist_t * | |||
| 647 | 563 | ||
| 648 | instproxy_lock(client); | 564 | instproxy_lock(client); |
| 649 | 565 | ||
| 650 | res = instproxy_plist_send(client, dict); | 566 | res = iphone_to_instproxy_error(iphone_device_send_xml_plist(client->connection, dict)); |
| 651 | plist_free(dict); | 567 | plist_free(dict); |
| 652 | 568 | ||
| 653 | if (res != INSTPROXY_E_SUCCESS) { | 569 | if (res != INSTPROXY_E_SUCCESS) { |
| @@ -655,7 +571,7 @@ instproxy_error_t instproxy_lookup_archives(instproxy_client_t client, plist_t * | |||
| 655 | goto leave_unlock; | 571 | goto leave_unlock; |
| 656 | } | 572 | } |
| 657 | 573 | ||
| 658 | res = instproxy_plist_recv(client, result); | 574 | res = iphone_to_instproxy_error(iphone_device_receive_plist(client->connection, result)); |
| 659 | if (res != INSTPROXY_E_SUCCESS) { | 575 | if (res != INSTPROXY_E_SUCCESS) { |
| 660 | log_dbg_msg(DBGMASK_INSTPROXY, "%s: could not receive plist, error %d\n", __func__, res); | 576 | log_dbg_msg(DBGMASK_INSTPROXY, "%s: could not receive plist, error %d\n", __func__, res); |
| 661 | goto leave_unlock; | 577 | goto leave_unlock; |
| @@ -718,7 +634,7 @@ instproxy_error_t instproxy_archive(instproxy_client_t client, const char *appid | |||
| 718 | plist_dict_insert_item(dict, "Command", plist_new_string("Archive")); | 634 | plist_dict_insert_item(dict, "Command", plist_new_string("Archive")); |
| 719 | 635 | ||
| 720 | instproxy_lock(client); | 636 | instproxy_lock(client); |
| 721 | res = instproxy_plist_send(client, dict); | 637 | res = iphone_to_instproxy_error(iphone_device_send_xml_plist(client->connection, dict)); |
| 722 | instproxy_unlock(client); | 638 | instproxy_unlock(client); |
| 723 | 639 | ||
| 724 | plist_free(dict); | 640 | plist_free(dict); |
| @@ -764,7 +680,7 @@ instproxy_error_t instproxy_restore(instproxy_client_t client, const char *appid | |||
| 764 | plist_dict_insert_item(dict, "Command", plist_new_string("Restore")); | 680 | plist_dict_insert_item(dict, "Command", plist_new_string("Restore")); |
| 765 | 681 | ||
| 766 | instproxy_lock(client); | 682 | instproxy_lock(client); |
| 767 | res = instproxy_plist_send(client, dict); | 683 | res = iphone_to_instproxy_error(iphone_device_send_xml_plist(client->connection, dict)); |
| 768 | instproxy_unlock(client); | 684 | instproxy_unlock(client); |
| 769 | 685 | ||
| 770 | plist_free(dict); | 686 | plist_free(dict); |
| @@ -810,7 +726,7 @@ instproxy_error_t instproxy_remove_archive(instproxy_client_t client, const char | |||
| 810 | plist_dict_insert_item(dict, "Command", plist_new_string("RemoveArchive")); | 726 | plist_dict_insert_item(dict, "Command", plist_new_string("RemoveArchive")); |
| 811 | 727 | ||
| 812 | instproxy_lock(client); | 728 | instproxy_lock(client); |
| 813 | res = instproxy_plist_send(client, dict); | 729 | res = iphone_to_instproxy_error(iphone_device_send_xml_plist(client->connection, dict)); |
| 814 | instproxy_unlock(client); | 730 | instproxy_unlock(client); |
| 815 | 731 | ||
| 816 | plist_free(dict); | 732 | plist_free(dict); |
diff --git a/src/MobileSync.c b/src/MobileSync.c index 77d2710..76aefa0 100644 --- a/src/MobileSync.c +++ b/src/MobileSync.c | |||
| @@ -31,6 +31,31 @@ | |||
| 31 | #define MSYNC_VERSION_INT1 100 | 31 | #define MSYNC_VERSION_INT1 100 |
| 32 | #define MSYNC_VERSION_INT2 100 | 32 | #define MSYNC_VERSION_INT2 100 |
| 33 | 33 | ||
| 34 | /** | ||
| 35 | * Convert an iphone_error_t value to an mobilesync_error_t value. | ||
| 36 | * Used internally to get correct error codes when using plist helper | ||
| 37 | * functions. | ||
| 38 | * | ||
| 39 | * @param err An iphone_error_t error code | ||
| 40 | * | ||
| 41 | * @return A matching mobilesync_error_t error code, | ||
| 42 | * MOBILESYNC_E_UNKNOWN_ERROR otherwise. | ||
| 43 | */ | ||
| 44 | static mobilesync_error_t iphone_to_mobilesync_error(iphone_error_t err) | ||
| 45 | { | ||
| 46 | switch (err) { | ||
| 47 | case IPHONE_E_SUCCESS: | ||
| 48 | return MOBILESYNC_E_SUCCESS; | ||
| 49 | case IPHONE_E_INVALID_ARG: | ||
| 50 | return MOBILESYNC_E_INVALID_ARG; | ||
| 51 | case IPHONE_E_PLIST_ERROR: | ||
| 52 | return MOBILESYNC_E_PLIST_ERROR; | ||
| 53 | default: | ||
| 54 | break; | ||
| 55 | } | ||
| 56 | return MOBILESYNC_E_UNKNOWN_ERROR; | ||
| 57 | } | ||
| 58 | |||
| 34 | mobilesync_error_t mobilesync_client_new(iphone_device_t device, int dst_port, | 59 | mobilesync_error_t mobilesync_client_new(iphone_device_t device, int dst_port, |
| 35 | mobilesync_client_t * client) | 60 | mobilesync_client_t * client) |
| 36 | { | 61 | { |
| @@ -160,35 +185,19 @@ mobilesync_error_t mobilesync_recv(mobilesync_client_t client, plist_t * plist) | |||
| 160 | { | 185 | { |
| 161 | if (!client || !plist || (plist && *plist)) | 186 | if (!client || !plist || (plist && *plist)) |
| 162 | return MOBILESYNC_E_INVALID_ARG; | 187 | return MOBILESYNC_E_INVALID_ARG; |
| 163 | mobilesync_error_t ret = MOBILESYNC_E_UNKNOWN_ERROR; | ||
| 164 | char *receive = NULL; | ||
| 165 | uint32_t datalen = 0, bytes = 0, received_bytes = 0; | ||
| 166 | |||
| 167 | ret = iphone_device_recv(client->connection, (char *) &datalen, sizeof(datalen), &bytes); | ||
| 168 | datalen = ntohl(datalen); | ||
| 169 | |||
| 170 | receive = (char *) malloc(sizeof(char) * datalen); | ||
| 171 | |||
| 172 | /* fill buffer and request more packets if needed */ | ||
| 173 | while ((received_bytes < datalen) && (ret == MOBILESYNC_E_SUCCESS)) { | ||
| 174 | ret = iphone_device_recv(client->connection, receive + received_bytes, datalen - received_bytes, &bytes); | ||
| 175 | received_bytes += bytes; | ||
| 176 | } | ||
| 177 | 188 | ||
| 189 | mobilesync_error_t ret = iphone_to_mobilesync_error(iphone_device_receive_plist(client->connection, plist)); | ||
| 178 | if (ret != MOBILESYNC_E_SUCCESS) { | 190 | if (ret != MOBILESYNC_E_SUCCESS) { |
| 179 | free(receive); | ||
| 180 | return MOBILESYNC_E_MUX_ERROR; | 191 | return MOBILESYNC_E_MUX_ERROR; |
| 181 | } | 192 | } |
| 182 | 193 | ||
| 183 | plist_from_bin(receive, received_bytes, plist); | 194 | #ifndef STRIP_DEBUG_CODE |
| 184 | free(receive); | ||
| 185 | |||
| 186 | char *XMLContent = NULL; | 195 | char *XMLContent = NULL; |
| 187 | uint32_t length = 0; | 196 | uint32_t length = 0; |
| 188 | plist_to_xml(*plist, &XMLContent, &length); | 197 | plist_to_xml(*plist, &XMLContent, &length); |
| 189 | log_dbg_msg(DBGMASK_MOBILESYNC, "%s: plist size: %i\nbuffer :\n%s\n", __func__, length, XMLContent); | 198 | log_dbg_msg(DBGMASK_MOBILESYNC, "%s: plist size: %i\nbuffer :\n%s\n", __func__, length, XMLContent); |
| 190 | free(XMLContent); | 199 | free(XMLContent); |
| 191 | 200 | #endif | |
| 192 | return ret; | 201 | return ret; |
| 193 | } | 202 | } |
| 194 | 203 | ||
| @@ -207,28 +216,12 @@ mobilesync_error_t mobilesync_send(mobilesync_client_t client, plist_t plist) | |||
| 207 | if (!client || !plist) | 216 | if (!client || !plist) |
| 208 | return MOBILESYNC_E_INVALID_ARG; | 217 | return MOBILESYNC_E_INVALID_ARG; |
| 209 | 218 | ||
| 219 | #ifndef STRIP_DEBUG_CODE | ||
| 210 | char *XMLContent = NULL; | 220 | char *XMLContent = NULL; |
| 211 | uint32_t length = 0; | 221 | uint32_t length = 0; |
| 212 | plist_to_xml(plist, &XMLContent, &length); | 222 | plist_to_xml(plist, &XMLContent, &length); |
| 213 | log_dbg_msg(DBGMASK_MOBILESYNC, "%s: plist size: %i\nbuffer :\n%s\n", __func__, length, XMLContent); | 223 | log_dbg_msg(DBGMASK_MOBILESYNC, "%s: plist size: %i\nbuffer :\n%s\n", __func__, length, XMLContent); |
| 214 | free(XMLContent); | 224 | free(XMLContent); |
| 215 | 225 | #endif | |
| 216 | char *content = NULL; | 226 | return (iphone_device_send_binary_plist(client->connection, plist) == IPHONE_E_SUCCESS ? MOBILESYNC_E_SUCCESS : MOBILESYNC_E_MUX_ERROR); |
| 217 | length = 0; | ||
| 218 | |||
| 219 | plist_to_bin(plist, &content, &length); | ||
| 220 | |||
| 221 | char *real_query; | ||
| 222 | int bytes; | ||
| 223 | mobilesync_error_t ret = MOBILESYNC_E_UNKNOWN_ERROR; | ||
| 224 | |||
| 225 | real_query = (char *) malloc(sizeof(char) * (length + 4)); | ||
| 226 | length = htonl(length); | ||
| 227 | memcpy(real_query, &length, sizeof(length)); | ||
| 228 | memcpy(real_query + 4, content, ntohl(length)); | ||
| 229 | |||
| 230 | ret = iphone_device_send(client->connection, real_query, ntohl(length) + sizeof(length), (uint32_t*)&bytes); | ||
| 231 | free(real_query); | ||
| 232 | return (ret == 0 ? MOBILESYNC_E_SUCCESS: MOBILESYNC_E_MUX_ERROR); | ||
| 233 | } | 227 | } |
| 234 | |||
diff --git a/src/NotificationProxy.c b/src/NotificationProxy.c index cba12b9..b73b521 100644 --- a/src/NotificationProxy.c +++ b/src/NotificationProxy.c | |||
| @@ -56,53 +56,28 @@ static void np_unlock(np_client_t client) | |||
| 56 | } | 56 | } |
| 57 | 57 | ||
| 58 | /** | 58 | /** |
| 59 | * Sends an xml plist to the device using the connection specified in client. | 59 | * Convert an iphone_error_t value to an np_error_t value. |
| 60 | * This function is only used internally. | 60 | * Used internally to get correct error codes when using plist helper |
| 61 | * functions. | ||
| 61 | * | 62 | * |
| 62 | * @param client NP to send data to | 63 | * @param err An iphone_error_t error code |
| 63 | * @param dict plist to send | ||
| 64 | * | 64 | * |
| 65 | * @return NP_E_SUCCESS on success, NP_E_INVALID_ARG when client or dict | 65 | * @return A matching np_error_t error code, |
| 66 | * are NULL, NP_E_PLIST_ERROR when dict is not a valid plist, | 66 | * NP_E_UNKNOWN_ERROR otherwise. |
| 67 | * or NP_E_UNKNOWN_ERROR when an unspecified error occurs. | ||
| 68 | */ | 67 | */ |
| 69 | static np_error_t np_plist_send(np_client_t client, plist_t dict) | 68 | static np_error_t iphone_to_np_error(iphone_error_t err) |
| 70 | { | 69 | { |
| 71 | char *XML_content = NULL; | 70 | switch (err) { |
| 72 | uint32_t length = 0; | 71 | case IPHONE_E_SUCCESS: |
| 73 | uint32_t nlen = 0; | 72 | return NP_E_SUCCESS; |
| 74 | int bytes = 0; | 73 | case IPHONE_E_INVALID_ARG: |
| 75 | np_error_t res = NP_E_UNKNOWN_ERROR; | 74 | return NP_E_INVALID_ARG; |
| 76 | 75 | case IPHONE_E_PLIST_ERROR: | |
| 77 | if (!client || !dict) { | 76 | return NP_E_PLIST_ERROR; |
| 78 | return NP_E_INVALID_ARG; | 77 | default: |
| 79 | } | 78 | break; |
| 80 | |||
| 81 | plist_to_xml(dict, &XML_content, &length); | ||
| 82 | |||
| 83 | if (!XML_content || length == 0) { | ||
| 84 | return NP_E_PLIST_ERROR; | ||
| 85 | } | ||
| 86 | |||
| 87 | nlen = htonl(length); | ||
| 88 | iphone_device_send(client->connection, (const char*)&nlen, sizeof(nlen), (uint32_t*)&bytes); | ||
| 89 | if (bytes == sizeof(nlen)) { | ||
| 90 | iphone_device_send(client->connection, XML_content, length, (uint32_t*)&bytes); | ||
| 91 | if (bytes > 0) { | ||
| 92 | if ((uint32_t)bytes == length) { | ||
| 93 | res = NP_E_SUCCESS; | ||
| 94 | } else { | ||
| 95 | log_debug_msg("%s: ERROR: Could not send all data (%d of %d)!\n", __func__, bytes, length); | ||
| 96 | } | ||
| 97 | } | ||
| 98 | } | ||
| 99 | if (bytes <= 0) { | ||
| 100 | log_debug_msg("%s: ERROR: sending to device failed.\n", __func__); | ||
| 101 | } | 79 | } |
| 102 | 80 | return NP_E_UNKNOWN_ERROR; | |
| 103 | free(XML_content); | ||
| 104 | |||
| 105 | return res; | ||
| 106 | } | 81 | } |
| 107 | 82 | ||
| 108 | /** Makes a connection to the NP service on the phone. | 83 | /** Makes a connection to the NP service on the phone. |
| @@ -185,13 +160,13 @@ np_error_t np_post_notification(np_client_t client, const char *notification) | |||
| 185 | plist_dict_insert_item(dict,"Command", plist_new_string("PostNotification")); | 160 | plist_dict_insert_item(dict,"Command", plist_new_string("PostNotification")); |
| 186 | plist_dict_insert_item(dict,"Name", plist_new_string(notification)); | 161 | plist_dict_insert_item(dict,"Name", plist_new_string(notification)); |
| 187 | 162 | ||
| 188 | np_error_t res = np_plist_send(client, dict); | 163 | np_error_t res = iphone_to_np_error(iphone_device_send_xml_plist(client->connection, dict)); |
| 189 | plist_free(dict); | 164 | plist_free(dict); |
| 190 | 165 | ||
| 191 | dict = plist_new_dict(); | 166 | dict = plist_new_dict(); |
| 192 | plist_dict_insert_item(dict,"Command", plist_new_string("Shutdown")); | 167 | plist_dict_insert_item(dict,"Command", plist_new_string("Shutdown")); |
| 193 | 168 | ||
| 194 | res = np_plist_send(client, dict); | 169 | res = iphone_to_np_error(iphone_device_send_xml_plist(client->connection, dict)); |
| 195 | plist_free(dict); | 170 | plist_free(dict); |
| 196 | 171 | ||
| 197 | if (res != NP_E_SUCCESS) { | 172 | if (res != NP_E_SUCCESS) { |
| @@ -221,7 +196,7 @@ np_error_t np_observe_notification( np_client_t client, const char *notification | |||
| 221 | plist_dict_insert_item(dict,"Command", plist_new_string("ObserveNotification")); | 196 | plist_dict_insert_item(dict,"Command", plist_new_string("ObserveNotification")); |
| 222 | plist_dict_insert_item(dict,"Name", plist_new_string(notification)); | 197 | plist_dict_insert_item(dict,"Name", plist_new_string(notification)); |
| 223 | 198 | ||
| 224 | np_error_t res = np_plist_send(client, dict); | 199 | np_error_t res = iphone_to_np_error(iphone_device_send_xml_plist(client->connection, dict)); |
| 225 | if (res != NP_E_SUCCESS) { | 200 | if (res != NP_E_SUCCESS) { |
| 226 | log_debug_msg("%s: Error sending XML plist to device!\n", __func__); | 201 | log_debug_msg("%s: Error sending XML plist to device!\n", __func__); |
| 227 | } | 202 | } |
| @@ -281,10 +256,7 @@ np_error_t np_observe_notifications(np_client_t client, const char **notificatio | |||
| 281 | */ | 256 | */ |
| 282 | static int np_get_notification(np_client_t client, char **notification) | 257 | static int np_get_notification(np_client_t client, char **notification) |
| 283 | { | 258 | { |
| 284 | uint32_t bytes = 0; | ||
| 285 | int res = 0; | 259 | int res = 0; |
| 286 | uint32_t pktlen = 0; | ||
| 287 | char *XML_content = NULL; | ||
| 288 | plist_t dict = NULL; | 260 | plist_t dict = NULL; |
| 289 | 261 | ||
| 290 | if (!client || !client->connection || *notification) | 262 | if (!client || !client->connection || *notification) |
| @@ -292,72 +264,46 @@ static int np_get_notification(np_client_t client, char **notification) | |||
| 292 | 264 | ||
| 293 | np_lock(client); | 265 | np_lock(client); |
| 294 | 266 | ||
| 295 | iphone_device_recv_timeout(client->connection, (char*)&pktlen, sizeof(pktlen), &bytes, 500); | 267 | iphone_device_receive_plist_with_timeout(client->connection, &dict, 500); |
| 296 | log_debug_msg("NotificationProxy: initial read=%i\n", bytes); | 268 | if (!dict) { |
| 297 | if (bytes < 4) { | ||
| 298 | log_debug_msg("NotificationProxy: no notification received!\n"); | 269 | log_debug_msg("NotificationProxy: no notification received!\n"); |
| 299 | res = 0; | 270 | res = 0; |
| 300 | } else { | 271 | } else { |
| 301 | if ((char)pktlen == 0) { | 272 | char *cmd_value = NULL; |
| 302 | pktlen = ntohl(pktlen); | 273 | plist_t cmd_value_node = plist_dict_get_item(dict, "Command"); |
| 303 | log_debug_msg("NotificationProxy: %d bytes following\n", pktlen); | 274 | |
| 304 | XML_content = (char*)malloc(pktlen); | 275 | if (plist_get_node_type(cmd_value_node) == PLIST_STRING) { |
| 305 | log_debug_msg("pointer %p\n", XML_content); | 276 | plist_get_string_val(cmd_value_node, &cmd_value); |
| 306 | 277 | } | |
| 307 | iphone_device_recv_timeout(client->connection, XML_content, pktlen, &bytes, 1000); | 278 | |
| 308 | if (bytes <= 0) { | 279 | if (cmd_value && !strcmp(cmd_value, "RelayNotification")) { |
| 309 | res = -1; | 280 | char *name_value = NULL; |
| 310 | } else { | 281 | plist_t name_value_node = plist_dict_get_item(dict, "Name"); |
| 311 | log_debug_msg("NotificationProxy: received data:\n"); | 282 | |
| 312 | log_debug_buffer(XML_content, pktlen); | 283 | if (plist_get_node_type(name_value_node) == PLIST_STRING) { |
| 313 | 284 | plist_get_string_val(name_value_node, &name_value); | |
| 314 | plist_from_xml(XML_content, bytes, &dict); | ||
| 315 | if (!dict) { | ||
| 316 | np_unlock(client); | ||
| 317 | return -2; | ||
| 318 | } | ||
| 319 | |||
| 320 | char *cmd_value = NULL; | ||
| 321 | plist_t cmd_value_node = plist_dict_get_item(dict, "Command"); | ||
| 322 | |||
| 323 | if (plist_get_node_type(cmd_value_node) == PLIST_STRING) { | ||
| 324 | plist_get_string_val(cmd_value_node, &cmd_value); | ||
| 325 | } | ||
| 326 | |||
| 327 | if (cmd_value && !strcmp(cmd_value, "RelayNotification")) { | ||
| 328 | char *name_value = NULL; | ||
| 329 | plist_t name_value_node = plist_dict_get_item(dict, "Name"); | ||
| 330 | |||
| 331 | if (plist_get_node_type(name_value_node) == PLIST_STRING) { | ||
| 332 | plist_get_string_val(name_value_node, &name_value); | ||
| 333 | } | ||
| 334 | |||
| 335 | res = -2; | ||
| 336 | if (name_value_node && name_value) { | ||
| 337 | *notification = name_value; | ||
| 338 | log_debug_msg("%s: got notification %s\n", __func__, name_value); | ||
| 339 | res = 0; | ||
| 340 | } | ||
| 341 | } else if (cmd_value && !strcmp(cmd_value, "ProxyDeath")) { | ||
| 342 | log_debug_msg("%s: ERROR: NotificationProxy died!\n", __func__); | ||
| 343 | res = -1; | ||
| 344 | } else if (cmd_value) { | ||
| 345 | log_debug_msg("%d: unknown NotificationProxy command '%s' received!\n", __func__); | ||
| 346 | res = -1; | ||
| 347 | } else { | ||
| 348 | res = -2; | ||
| 349 | } | ||
| 350 | if (cmd_value) { | ||
| 351 | free(cmd_value); | ||
| 352 | } | ||
| 353 | plist_free(dict); | ||
| 354 | dict = NULL; | ||
| 355 | free(XML_content); | ||
| 356 | XML_content = NULL; | ||
| 357 | } | 285 | } |
| 358 | } else { | 286 | |
| 287 | res = -2; | ||
| 288 | if (name_value_node && name_value) { | ||
| 289 | *notification = name_value; | ||
| 290 | log_debug_msg("%s: got notification %s\n", __func__, name_value); | ||
| 291 | res = 0; | ||
| 292 | } | ||
| 293 | } else if (cmd_value && !strcmp(cmd_value, "ProxyDeath")) { | ||
| 294 | log_debug_msg("%s: ERROR: NotificationProxy died!\n", __func__); | ||
| 359 | res = -1; | 295 | res = -1; |
| 296 | } else if (cmd_value) { | ||
| 297 | log_debug_msg("%d: unknown NotificationProxy command '%s' received!\n", __func__); | ||
| 298 | res = -1; | ||
| 299 | } else { | ||
| 300 | res = -2; | ||
| 301 | } | ||
| 302 | if (cmd_value) { | ||
| 303 | free(cmd_value); | ||
| 360 | } | 304 | } |
| 305 | plist_free(dict); | ||
| 306 | dict = NULL; | ||
| 361 | } | 307 | } |
| 362 | 308 | ||
| 363 | np_unlock(client); | 309 | np_unlock(client); |
diff --git a/src/SBServices.c b/src/SBServices.c index 9849415..1296245 100644 --- a/src/SBServices.c +++ b/src/SBServices.c | |||
| @@ -87,112 +87,39 @@ sbservices_error_t sbservices_client_free(sbservices_client_t client) | |||
| 87 | return SBSERVICES_E_SUCCESS; | 87 | return SBSERVICES_E_SUCCESS; |
| 88 | } | 88 | } |
| 89 | 89 | ||
| 90 | /** | ||
| 91 | * Sends a binary plist to the device using the connection specified in client. | ||
| 92 | * This function is only used internally. | ||
| 93 | * | ||
| 94 | * @param client InstallationProxy to send data to | ||
| 95 | * @param dict plist to send | ||
| 96 | * | ||
| 97 | * @return SBSERVICES_E_SUCCESS on success, SBSERVICES_E_INVALID_ARG when | ||
| 98 | * client or dict are NULL, SBSERVICES_E_PLIST_ERROR when dict is not a | ||
| 99 | * valid plist, or SBSERVICES_E_UNKNOWN_ERROR when an unspecified error | ||
| 100 | * occurs. | ||
| 101 | */ | ||
| 102 | static sbservices_error_t sbservices_plist_send(sbservices_client_t client, plist_t dict) | ||
| 103 | { | ||
| 104 | char *content = NULL; | ||
| 105 | uint32_t length = 0; | ||
| 106 | uint32_t nlen = 0; | ||
| 107 | int bytes = 0; | ||
| 108 | sbservices_error_t res = SBSERVICES_E_UNKNOWN_ERROR; | ||
| 109 | |||
| 110 | if (!client || !dict) { | ||
| 111 | return SBSERVICES_E_INVALID_ARG; | ||
| 112 | } | ||
| 113 | |||
| 114 | plist_to_bin(dict, &content, &length); | ||
| 115 | |||
| 116 | if (!content || length == 0) { | ||
| 117 | return SBSERVICES_E_PLIST_ERROR; | ||
| 118 | } | ||
| 119 | |||
| 120 | nlen = htonl(length); | ||
| 121 | log_debug_msg("%s: sending %d bytes\n", __func__, length); | ||
| 122 | iphone_device_send(client->connection, (const char*)&nlen, sizeof(nlen), (uint32_t*)&bytes); | ||
| 123 | if (bytes == sizeof(nlen)) { | ||
| 124 | iphone_device_send(client->connection, content, length, (uint32_t*)&bytes); | ||
| 125 | if (bytes > 0) { | ||
| 126 | if ((uint32_t)bytes == length) { | ||
| 127 | res = SBSERVICES_E_SUCCESS; | ||
| 128 | } else { | ||
| 129 | log_debug_msg("%s: ERROR: Could not send all data (%d of %d)!\n", __func__, bytes, length); | ||
| 130 | } | ||
| 131 | } | ||
| 132 | } | ||
| 133 | if (bytes <= 0) { | ||
| 134 | log_debug_msg("%s: ERROR: sending to device failed.\n", __func__); | ||
| 135 | } | ||
| 136 | |||
| 137 | free(content); | ||
| 138 | |||
| 139 | return res; | ||
| 140 | } | ||
| 141 | |||
| 142 | sbservices_error_t sbservices_get_icon_state(sbservices_client_t client, plist_t *state) | 90 | sbservices_error_t sbservices_get_icon_state(sbservices_client_t client, plist_t *state) |
| 143 | { | 91 | { |
| 144 | if (!client || !client->connection || !state) | 92 | if (!client || !client->connection || !state) |
| 145 | return SBSERVICES_E_INVALID_ARG; | 93 | return SBSERVICES_E_INVALID_ARG; |
| 146 | 94 | ||
| 147 | sbservices_error_t res = SBSERVICES_E_UNKNOWN_ERROR; | 95 | sbservices_error_t res = SBSERVICES_E_UNKNOWN_ERROR; |
| 148 | uint32_t pktlen = 0; | ||
| 149 | uint32_t bytes = 0; | ||
| 150 | 96 | ||
| 151 | plist_t dict = plist_new_dict(); | 97 | plist_t dict = plist_new_dict(); |
| 152 | plist_dict_insert_item(dict, "command", plist_new_string("getIconState")); | 98 | plist_dict_insert_item(dict, "command", plist_new_string("getIconState")); |
| 153 | 99 | ||
| 154 | sbs_lock(client); | 100 | sbs_lock(client); |
| 155 | 101 | ||
| 156 | res = sbservices_plist_send(client, dict); | 102 | if (iphone_device_send_binary_plist(client->connection, dict) != IPHONE_E_SUCCESS) { |
| 157 | plist_free(dict); | ||
| 158 | if (res != SBSERVICES_E_SUCCESS) { | ||
| 159 | log_debug_msg("%s: could not send plist\n", __func__); | 103 | log_debug_msg("%s: could not send plist\n", __func__); |
| 160 | goto leave_unlock; | 104 | goto leave_unlock; |
| 161 | } | 105 | } |
| 106 | plist_free(dict); | ||
| 107 | dict = NULL; | ||
| 162 | 108 | ||
| 163 | iphone_device_recv(client->connection, (char*)&pktlen, sizeof(pktlen), &bytes); | 109 | if (iphone_device_receive_plist(client->connection, state) == IPHONE_E_SUCCESS) { |
| 164 | log_debug_msg("%s: initial read=%i\n", __func__, bytes); | 110 | res = SBSERVICES_E_SUCCESS; |
| 165 | if (bytes < 4) { | ||
| 166 | log_debug_msg("%s: initial read failed!\n"); | ||
| 167 | res = 0; | ||
| 168 | } else { | 111 | } else { |
| 169 | if ((char)pktlen == 0) { | 112 | log_debug_msg("%s: could not get icon state!\n", __func__); |
| 170 | char *content = NULL; | 113 | if (*state) { |
| 171 | uint32_t curlen = 0; | 114 | plist_free(*state); |
| 172 | pktlen = ntohl(pktlen); | 115 | *state = NULL; |
| 173 | log_debug_msg("%s: %d bytes following\n", __func__, pktlen); | ||
| 174 | content = (char*)malloc(pktlen); | ||
| 175 | log_debug_msg("pointer %p\n", content); | ||
| 176 | |||
| 177 | while (curlen < pktlen) { | ||
| 178 | iphone_device_recv(client->connection, content+curlen, pktlen-curlen, &bytes); | ||
| 179 | if (bytes <= 0) { | ||
| 180 | res = SBSERVICES_E_UNKNOWN_ERROR; | ||
| 181 | break; | ||
| 182 | } | ||
| 183 | log_debug_msg("%s: received %d bytes\n", __func__, bytes); | ||
| 184 | curlen += bytes; | ||
| 185 | } | ||
| 186 | log_debug_buffer(content, pktlen); | ||
| 187 | plist_from_bin(content, pktlen, state); | ||
| 188 | res = SBSERVICES_E_SUCCESS; | ||
| 189 | free(content); | ||
| 190 | } else { | ||
| 191 | res = SBSERVICES_E_UNKNOWN_ERROR; | ||
| 192 | } | 116 | } |
| 193 | } | 117 | } |
| 194 | 118 | ||
| 195 | leave_unlock: | 119 | leave_unlock: |
| 120 | if (dict) { | ||
| 121 | plist_free(dict); | ||
| 122 | } | ||
| 196 | sbs_unlock(client); | 123 | sbs_unlock(client); |
| 197 | return res; | 124 | return res; |
| 198 | } | 125 | } |
| @@ -210,15 +137,16 @@ sbservices_error_t sbservices_set_icon_state(sbservices_client_t client, plist_t | |||
| 210 | 137 | ||
| 211 | sbs_lock(client); | 138 | sbs_lock(client); |
| 212 | 139 | ||
| 213 | res = sbservices_plist_send(client, dict); | 140 | if (iphone_device_send_binary_plist(client->connection, dict) != IPHONE_E_SUCCESS) { |
| 214 | plist_free(dict); | ||
| 215 | if (res != SBSERVICES_E_SUCCESS) { | ||
| 216 | log_debug_msg("%s: could not send plist\n", __func__); | 141 | log_debug_msg("%s: could not send plist\n", __func__); |
| 217 | goto leave_unlock; | 142 | goto leave_unlock; |
| 218 | } | 143 | } |
| 219 | // NO RESPONSE | 144 | // NO RESPONSE |
| 220 | 145 | ||
| 221 | leave_unlock: | 146 | leave_unlock: |
| 147 | if (dict) { | ||
| 148 | plist_free(dict); | ||
| 149 | } | ||
| 222 | sbs_unlock(client); | 150 | sbs_unlock(client); |
| 223 | return res; | 151 | return res; |
| 224 | } | 152 | } |
| @@ -229,8 +157,6 @@ sbservices_error_t sbservices_get_icon_pngdata(sbservices_client_t client, const | |||
| 229 | return SBSERVICES_E_INVALID_ARG; | 157 | return SBSERVICES_E_INVALID_ARG; |
| 230 | 158 | ||
| 231 | sbservices_error_t res = SBSERVICES_E_UNKNOWN_ERROR; | 159 | sbservices_error_t res = SBSERVICES_E_UNKNOWN_ERROR; |
| 232 | uint32_t pktlen = 0; | ||
| 233 | uint32_t bytes = 0; | ||
| 234 | 160 | ||
| 235 | plist_t dict = plist_new_dict(); | 161 | plist_t dict = plist_new_dict(); |
| 236 | plist_dict_insert_item(dict, "command", plist_new_string("getIconPNGData")); | 162 | plist_dict_insert_item(dict, "command", plist_new_string("getIconPNGData")); |
| @@ -238,52 +164,25 @@ sbservices_error_t sbservices_get_icon_pngdata(sbservices_client_t client, const | |||
| 238 | 164 | ||
| 239 | sbs_lock(client); | 165 | sbs_lock(client); |
| 240 | 166 | ||
| 241 | res = sbservices_plist_send(client, dict); | 167 | if (iphone_device_send_binary_plist(client->connection, dict) != IPHONE_E_SUCCESS) { |
| 242 | plist_free(dict); | ||
| 243 | if (res != SBSERVICES_E_SUCCESS) { | ||
| 244 | log_debug_msg("%s: could not send plist\n", __func__); | 168 | log_debug_msg("%s: could not send plist\n", __func__); |
| 245 | goto leave_unlock; | 169 | goto leave_unlock; |
| 246 | } | 170 | } |
| 171 | plist_free(dict); | ||
| 247 | 172 | ||
| 248 | iphone_device_recv(client->connection, (char*)&pktlen, sizeof(pktlen), &bytes); | 173 | dict = NULL; |
| 249 | log_debug_msg("%s: initial read=%i\n", __func__, bytes); | 174 | if (iphone_device_receive_plist(client->connection, &dict) == IPHONE_E_SUCCESS) { |
| 250 | if (bytes < 4) { | 175 | plist_t node = plist_dict_get_item(dict, "pngData"); |
| 251 | log_debug_msg("%s: initial read failed!\n"); | 176 | if (node) { |
| 252 | res = 0; | 177 | plist_get_data_val(node, pngdata, pngsize); |
| 253 | } else { | ||
| 254 | if ((char)pktlen == 0) { | ||
| 255 | char *content = NULL; | ||
| 256 | uint32_t curlen = 0; | ||
| 257 | pktlen = ntohl(pktlen); | ||
| 258 | log_debug_msg("%s: %d bytes following\n", __func__, pktlen); | ||
| 259 | content = (char*)malloc(pktlen); | ||
| 260 | log_debug_msg("pointer %p\n", content); | ||
| 261 | |||
| 262 | while (curlen < pktlen) { | ||
| 263 | iphone_device_recv(client->connection, content+curlen, pktlen-curlen, &bytes); | ||
| 264 | if (bytes <= 0) { | ||
| 265 | res = SBSERVICES_E_UNKNOWN_ERROR; | ||
| 266 | break; | ||
| 267 | } | ||
| 268 | log_debug_msg("%s: received %d bytes\n", __func__, bytes); | ||
| 269 | curlen += bytes; | ||
| 270 | } | ||
| 271 | log_debug_buffer(content, pktlen); | ||
| 272 | plist_t pngdict = NULL; | ||
| 273 | plist_from_bin(content, pktlen, &pngdict); | ||
| 274 | plist_t node = plist_dict_get_item(pngdict, "pngData"); | ||
| 275 | if (node) { | ||
| 276 | plist_get_data_val(node, pngdata, pngsize); | ||
| 277 | } | ||
| 278 | plist_free(pngdict); | ||
| 279 | res = SBSERVICES_E_SUCCESS; | ||
| 280 | free(content); | ||
| 281 | } else { | ||
| 282 | res = SBSERVICES_E_UNKNOWN_ERROR; | ||
| 283 | } | 178 | } |
| 179 | res = SBSERVICES_E_SUCCESS; | ||
| 284 | } | 180 | } |
| 285 | 181 | ||
| 286 | leave_unlock: | 182 | leave_unlock: |
| 183 | if (dict) { | ||
| 184 | plist_free(dict); | ||
| 185 | } | ||
| 287 | sbs_unlock(client); | 186 | sbs_unlock(client); |
| 288 | return res; | 187 | return res; |
| 289 | 188 | ||
diff --git a/src/iphone.c b/src/iphone.c index 586b3bc..3c13859 100644 --- a/src/iphone.c +++ b/src/iphone.c | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | #include <stdlib.h> | 23 | #include <stdlib.h> |
| 24 | #include <string.h> | 24 | #include <string.h> |
| 25 | #include <errno.h> | 25 | #include <errno.h> |
| 26 | #include <arpa/inet.h> | ||
| 26 | 27 | ||
| 27 | #include <usbmuxd.h> | 28 | #include <usbmuxd.h> |
| 28 | #include "iphone.h" | 29 | #include "iphone.h" |
| @@ -350,6 +351,286 @@ iphone_error_t iphone_device_recv(iphone_connection_t connection, char *data, ui | |||
| 350 | return IPHONE_E_UNKNOWN_ERROR; | 351 | return IPHONE_E_UNKNOWN_ERROR; |
| 351 | } | 352 | } |
| 352 | 353 | ||
| 354 | /** | ||
| 355 | * Sends a plist over the given connection. | ||
| 356 | * Internally used generic plist send function. | ||
| 357 | * | ||
| 358 | * @param connection The connection to use for sending. | ||
| 359 | * Can be NULL if ssl_session is non-NULL. | ||
| 360 | * @param plist plist to send | ||
| 361 | * @param binary 1 = send binary plist, 0 = send xml plist | ||
| 362 | * @param ssl_session If set to NULL, the communication will be unencrypted. | ||
| 363 | * For encrypted communication, pass a valid and properly initialized | ||
| 364 | * gnutls_session_t. connection is ignored when ssl_session is non-NULL. | ||
| 365 | * | ||
| 366 | * @return IPHONE_E_SUCCESS on success, IPHONE_E_INVALID_ARG when one or more | ||
| 367 | * parameters are invalid, IPHONE_E_PLIST_ERROR when dict is not a valid | ||
| 368 | * plist, or IPHONE_E_UNKNOWN_ERROR when an unspecified error occurs. | ||
| 369 | */ | ||
| 370 | static iphone_error_t internal_plist_send(iphone_connection_t connection, plist_t plist, int binary, gnutls_session_t ssl_session) | ||
| 371 | { | ||
| 372 | iphone_error_t res = IPHONE_E_UNKNOWN_ERROR; | ||
| 373 | char *content = NULL; | ||
| 374 | uint32_t length = 0; | ||
| 375 | uint32_t nlen = 0; | ||
| 376 | int bytes = 0; | ||
| 377 | |||
| 378 | if ((!connection && !ssl_session) || !plist) { | ||
| 379 | return IPHONE_E_INVALID_ARG; | ||
| 380 | } | ||
| 381 | |||
| 382 | if (binary) { | ||
| 383 | plist_to_bin(plist, &content, &length); | ||
| 384 | } else { | ||
| 385 | plist_to_xml(plist, &content, &length); | ||
| 386 | } | ||
| 387 | |||
| 388 | if (!content || length == 0) { | ||
| 389 | return IPHONE_E_PLIST_ERROR; | ||
| 390 | } | ||
| 391 | |||
| 392 | nlen = htonl(length); | ||
| 393 | log_debug_msg("%s: sending %d bytes\n", __func__, length); | ||
| 394 | if (ssl_session) { | ||
| 395 | bytes = gnutls_record_send(ssl_session, (const char*)&nlen, sizeof(nlen)); | ||
| 396 | } else { | ||
| 397 | iphone_device_send(connection, (const char*)&nlen, sizeof(nlen), (uint32_t*)&bytes); | ||
| 398 | } | ||
| 399 | if (bytes == sizeof(nlen)) { | ||
| 400 | if (ssl_session) { | ||
| 401 | bytes = gnutls_record_send(ssl_session, content, length); | ||
| 402 | } else { | ||
| 403 | iphone_device_send(connection, content, length, (uint32_t*)&bytes); | ||
| 404 | } | ||
| 405 | if (bytes > 0) { | ||
| 406 | log_debug_msg("%s: received %d bytes\n", __func__, bytes); | ||
| 407 | log_debug_buffer(content, bytes); | ||
| 408 | if ((uint32_t)bytes == length) { | ||
| 409 | res = IPHONE_E_SUCCESS; | ||
| 410 | } else { | ||
| 411 | log_debug_msg("%s: ERROR: Could not send all data (%d of %d)!\n", __func__, bytes, length); | ||
| 412 | } | ||
| 413 | } | ||
| 414 | } | ||
| 415 | if (bytes <= 0) { | ||
| 416 | log_debug_msg("%s: ERROR: sending to device failed.\n", __func__); | ||
| 417 | } | ||
| 418 | |||
| 419 | free(content); | ||
| 420 | |||
| 421 | return res; | ||
| 422 | } | ||
| 423 | |||
| 424 | /** | ||
| 425 | * Sends an XML plist over the given connection. | ||
| 426 | * | ||
| 427 | * @param connection The connection to send data over | ||
| 428 | * @param plist plist to send | ||
| 429 | * | ||
| 430 | * @return IPHONE_E_SUCCESS on success, IPHONE_E_INVALID_ARG when connection | ||
| 431 | * or plist is NULL, IPHONE_E_PLIST_ERROR when dict is not a valid plist, | ||
| 432 | * or IPHONE_E_UNKNOWN_ERROR when an unspecified error occurs. | ||
| 433 | */ | ||
| 434 | iphone_error_t iphone_device_send_xml_plist(iphone_connection_t connection, plist_t plist) | ||
| 435 | { | ||
| 436 | return internal_plist_send(connection, plist, 0, NULL); | ||
| 437 | } | ||
| 438 | |||
| 439 | /** | ||
| 440 | * Sends a binary plist over the given connection. | ||
| 441 | * | ||
| 442 | * @param connection The connection to send data over | ||
| 443 | * @param plist plist to send | ||
| 444 | * | ||
| 445 | * @return IPHONE_E_SUCCESS on success, IPHONE_E_INVALID_ARG when connection | ||
| 446 | * or plist is NULL, IPHONE_E_PLIST_ERROR when dict is not a valid plist, | ||
| 447 | * or IPHONE_E_UNKNOWN_ERROR when an unspecified error occurs. | ||
| 448 | */ | ||
| 449 | iphone_error_t iphone_device_send_binary_plist(iphone_connection_t connection, plist_t plist) | ||
| 450 | { | ||
| 451 | return internal_plist_send(connection, plist, 1, NULL); | ||
| 452 | } | ||
| 453 | |||
| 454 | /** | ||
| 455 | * Sends an encrypted XML plist. | ||
| 456 | * | ||
| 457 | * @param ssl_session Valid and properly initialized gnutls_session_t. | ||
| 458 | * @param plist plist to send | ||
| 459 | * | ||
| 460 | * @return IPHONE_E_SUCCESS on success, IPHONE_E_INVALID_ARG when ssl_session | ||
| 461 | * or plist is NULL, IPHONE_E_PLIST_ERROR when dict is not a valid plist, | ||
| 462 | * or IPHONE_E_UNKNOWN_ERROR when an unspecified error occurs. | ||
| 463 | */ | ||
| 464 | iphone_error_t iphone_device_send_encrypted_xml_plist(gnutls_session_t ssl_session, plist_t plist) | ||
| 465 | { | ||
| 466 | return internal_plist_send(NULL, plist, 0, ssl_session); | ||
| 467 | } | ||
| 468 | |||
| 469 | /** | ||
| 470 | * Sends an encrypted binary plist. | ||
| 471 | * | ||
| 472 | * @param ssl_session Valid and properly initialized gnutls_session_t. | ||
| 473 | * @param plist plist to send | ||
| 474 | * | ||
| 475 | * @return IPHONE_E_SUCCESS on success, IPHONE_E_INVALID_ARG when ssl_session | ||
| 476 | * or plist is NULL, IPHONE_E_PLIST_ERROR when dict is not a valid plist, | ||
| 477 | * or IPHONE_E_UNKNOWN_ERROR when an unspecified error occurs. | ||
| 478 | */ | ||
| 479 | iphone_error_t iphone_device_send_encrypted_binary_plist(gnutls_session_t ssl_session, plist_t plist) | ||
| 480 | { | ||
| 481 | return internal_plist_send(NULL, plist, 1, ssl_session); | ||
| 482 | } | ||
| 483 | |||
| 484 | /** | ||
| 485 | * Receives a plist over the given connection. | ||
| 486 | * Internally used generic plist send function. | ||
| 487 | * | ||
| 488 | * @param connection The connection to receive data on | ||
| 489 | * @param plist pointer to a plist_t that will point to the received plist | ||
| 490 | * upon successful return | ||
| 491 | * @param timeout Maximum time in milliseconds to wait for data. | ||
| 492 | * @param ssl_session If set to NULL, the communication will be unencrypted. | ||
| 493 | * For encrypted communication, pass a valid and properly initialized | ||
| 494 | * gnutls_session_t. | ||
| 495 | * | ||
| 496 | * @return IPHONE_E_SUCCESS on success, IPHONE_E_INVALID_ARG when connection | ||
| 497 | * or *plist is NULL, IPHONE_E_PLIST_ERROR when the received data cannot be | ||
| 498 | * converted to a plist, or IPHONE_E_UNKNOWN_ERROR when an unspecified | ||
| 499 | * error occurs. | ||
| 500 | */ | ||
| 501 | static iphone_error_t internal_plist_recv_timeout(iphone_connection_t connection, plist_t *plist, unsigned int timeout, gnutls_session_t ssl_session) | ||
| 502 | { | ||
| 503 | iphone_error_t res = IPHONE_E_UNKNOWN_ERROR; | ||
| 504 | uint32_t pktlen = 0; | ||
| 505 | uint32_t bytes = 0; | ||
| 506 | |||
| 507 | if ((!connection && !ssl_session) || !plist) { | ||
| 508 | return IPHONE_E_INVALID_ARG; | ||
| 509 | } | ||
| 510 | |||
| 511 | iphone_device_recv_timeout(connection, (char*)&pktlen, sizeof(pktlen), &bytes, timeout); | ||
| 512 | log_debug_msg("%s: initial read=%i\n", __func__, bytes); | ||
| 513 | if (bytes < 4) { | ||
| 514 | log_debug_msg("%s: initial read failed!\n", __func__); | ||
| 515 | return IPHONE_E_NOT_ENOUGH_DATA; | ||
| 516 | } else { | ||
| 517 | if ((char)pktlen == 0) { /* prevent huge buffers */ | ||
| 518 | uint32_t curlen = 0; | ||
| 519 | char *content = NULL; | ||
| 520 | pktlen = ntohl(pktlen); | ||
| 521 | log_debug_msg("%s: %d bytes following\n", __func__, pktlen); | ||
| 522 | content = (char*)malloc(pktlen); | ||
| 523 | |||
| 524 | while (curlen < pktlen) { | ||
| 525 | iphone_device_recv(connection, content+curlen, pktlen-curlen, &bytes); | ||
| 526 | if (bytes <= 0) { | ||
| 527 | res = IPHONE_E_UNKNOWN_ERROR; | ||
| 528 | break; | ||
| 529 | } | ||
| 530 | log_debug_msg("%s: received %d bytes\n", __func__, bytes); | ||
| 531 | curlen += bytes; | ||
| 532 | } | ||
| 533 | log_debug_buffer(content, pktlen); | ||
| 534 | if (!memcmp(content, "bplist00", 8)) { | ||
| 535 | plist_from_bin(content, pktlen, plist); | ||
| 536 | } else { | ||
| 537 | plist_from_xml(content, pktlen, plist); | ||
| 538 | } | ||
| 539 | if (*plist) { | ||
| 540 | res = IPHONE_E_SUCCESS; | ||
| 541 | } else { | ||
| 542 | res = IPHONE_E_PLIST_ERROR; | ||
| 543 | } | ||
| 544 | free(content); | ||
| 545 | content = NULL; | ||
| 546 | } else { | ||
| 547 | res = IPHONE_E_UNKNOWN_ERROR; | ||
| 548 | } | ||
| 549 | } | ||
| 550 | return res; | ||
| 551 | } | ||
| 552 | |||
| 553 | /** | ||
| 554 | * Receives a plist over the given connection with specified timeout. | ||
| 555 | * Binary or XML plists are automatically handled. | ||
| 556 | * | ||
| 557 | * @param connection The connection to receive data on | ||
| 558 | * @param plist pointer to a plist_t that will point to the received plist | ||
| 559 | * upon successful return | ||
| 560 | * @param timeout Maximum time in milliseconds to wait for data. | ||
| 561 | * | ||
| 562 | * @return IPHONE_E_SUCCESS on success, IPHONE_E_INVALID_ARG when connection | ||
| 563 | * or *plist is NULL, IPHONE_E_PLIST_ERROR when the received data cannot be | ||
| 564 | * converted to a plist, or IPHONE_E_UNKNOWN_ERROR when an unspecified | ||
| 565 | * error occurs. | ||
| 566 | */ | ||
| 567 | iphone_error_t iphone_device_receive_plist_with_timeout(iphone_connection_t connection, plist_t *plist, unsigned int timeout) | ||
| 568 | { | ||
| 569 | return internal_plist_recv_timeout(connection, plist, timeout, NULL); | ||
| 570 | } | ||
| 571 | |||
| 572 | /** | ||
| 573 | * Receives a plist over the given connection. | ||
| 574 | * Binary or XML plists are automatically handled. | ||
| 575 | * | ||
| 576 | * This function is like iphone_device_receive_plist_with_timeout | ||
| 577 | * using a timeout of 10 seconds. | ||
| 578 | * @see iphone_device_receive_plist_with_timeout | ||
| 579 | * | ||
| 580 | * @param connection The connection to receive data on | ||
| 581 | * @param plist pointer to a plist_t that will point to the received plist | ||
| 582 | * upon successful return | ||
| 583 | * | ||
| 584 | * @return IPHONE_E_SUCCESS on success, IPHONE_E_INVALID_ARG when connection | ||
| 585 | * or *plist is NULL, IPHONE_E_PLIST_ERROR when the received data cannot be | ||
| 586 | * converted to a plist, or IPHONE_E_UNKNOWN_ERROR when an unspecified | ||
| 587 | * error occurs. | ||
| 588 | */ | ||
| 589 | iphone_error_t iphone_device_receive_plist(iphone_connection_t connection, plist_t *plist) | ||
| 590 | { | ||
| 591 | return internal_plist_recv_timeout(connection, plist, 10000, NULL); | ||
| 592 | } | ||
| 593 | |||
| 594 | /** | ||
| 595 | * Receives an encrypted plist with specified timeout. | ||
| 596 | * Binary or XML plists are automatically handled. | ||
| 597 | * | ||
| 598 | * @param ssl_session Valid and properly initialized gnutls_session_t. | ||
| 599 | * @param plist pointer to a plist_t that will point to the received plist | ||
| 600 | * upon successful return | ||
| 601 | * @param timeout Maximum time in milliseconds to wait for data. | ||
| 602 | * | ||
| 603 | * @return IPHONE_E_SUCCESS on success, IPHONE_E_INVALID_ARG when ssl_session | ||
| 604 | * or *plist is NULL, IPHONE_E_PLIST_ERROR when the received data cannot be | ||
| 605 | * converted to a plist, or IPHONE_E_UNKNOWN_ERROR when an unspecified | ||
| 606 | * error occurs. | ||
| 607 | */ | ||
| 608 | iphone_error_t iphone_device_receive_encrypted_plist_with_timeout(gnutls_session_t ssl_session, plist_t *plist, unsigned int timeout) | ||
| 609 | { | ||
| 610 | return internal_plist_recv_timeout(NULL, plist, timeout, ssl_session); | ||
| 611 | } | ||
| 612 | |||
| 613 | /** | ||
| 614 | * Receives an encrypted plist. | ||
| 615 | * Binary or XML plists are automatically handled. | ||
| 616 | * This function is like iphone_device_receive_encrypted_plist_with_timeout | ||
| 617 | * with a timeout value of 10 seconds. | ||
| 618 | * | ||
| 619 | * @param ssl_session Valid and properly initialized gnutls_session_t. | ||
| 620 | * @param connection The connection to receive data on | ||
| 621 | * @param plist pointer to a plist_t that will point to the received plist | ||
| 622 | * upon successful return | ||
| 623 | * | ||
| 624 | * @return IPHONE_E_SUCCESS on success, IPHONE_E_INVALID_ARG when ssl_session | ||
| 625 | * or *plist is NULL, IPHONE_E_PLIST_ERROR when the received data cannot be | ||
| 626 | * converted to a plist, or IPHONE_E_UNKNOWN_ERROR when an unspecified | ||
| 627 | * error occurs. | ||
| 628 | */ | ||
| 629 | iphone_error_t iphone_device_receive_encrypted_plist(gnutls_session_t ssl_session, plist_t *plist) | ||
| 630 | { | ||
| 631 | return internal_plist_recv_timeout(NULL, plist, 10000, ssl_session); | ||
| 632 | } | ||
| 633 | |||
| 353 | iphone_error_t iphone_device_get_handle(iphone_device_t device, uint32_t *handle) | 634 | iphone_error_t iphone_device_get_handle(iphone_device_t device, uint32_t *handle) |
| 354 | { | 635 | { |
| 355 | if (!device) | 636 | if (!device) |
diff --git a/src/iphone.h b/src/iphone.h index 98b0ed8..7ffc811 100644 --- a/src/iphone.h +++ b/src/iphone.h | |||
| @@ -21,6 +21,9 @@ | |||
| 21 | #ifndef IPHONE_H | 21 | #ifndef IPHONE_H |
| 22 | #define IPHONE_H | 22 | #define IPHONE_H |
| 23 | 23 | ||
| 24 | #include <plist/plist.h> | ||
| 25 | #include <gnutls/gnutls.h> | ||
| 26 | |||
| 24 | #include "libiphone/libiphone.h" | 27 | #include "libiphone/libiphone.h" |
| 25 | 28 | ||
| 26 | enum connection_type { | 29 | enum connection_type { |
| @@ -38,4 +41,14 @@ struct iphone_device_int { | |||
| 38 | void *conn_data; | 41 | void *conn_data; |
| 39 | }; | 42 | }; |
| 40 | 43 | ||
| 44 | iphone_error_t iphone_device_send_xml_plist(iphone_connection_t connection, plist_t plist); | ||
| 45 | iphone_error_t iphone_device_send_binary_plist(iphone_connection_t connection, plist_t plist); | ||
| 46 | iphone_error_t iphone_device_send_encrypted_xml_plist(gnutls_session_t ssl_session, plist_t plist); | ||
| 47 | iphone_error_t iphone_device_send_encrypted_binary_plist(gnutls_session_t ssl_session, plist_t plist); | ||
| 48 | |||
| 49 | iphone_error_t iphone_device_receive_plist_with_timeout(iphone_connection_t connection, plist_t *plist, unsigned int timeout); | ||
| 50 | iphone_error_t iphone_device_receive_plist(iphone_connection_t connection, plist_t *plist); | ||
| 51 | iphone_error_t iphone_device_receive_encrypted_plist_with_timeout(gnutls_session_t ssl_session, plist_t *plist, unsigned int timeout); | ||
| 52 | iphone_error_t iphone_device_receive_encrypted_plist(gnutls_session_t ssl_session, plist_t *plist); | ||
| 53 | |||
| 41 | #endif | 54 | #endif |
diff --git a/src/lockdown.c b/src/lockdown.c index 1b33830..24dd4a1 100644 --- a/src/lockdown.c +++ b/src/lockdown.c | |||
| @@ -271,61 +271,21 @@ lockdownd_error_t lockdownd_recv(lockdownd_client_t client, plist_t *plist) | |||
| 271 | { | 271 | { |
| 272 | if (!client || !plist || (plist && *plist)) | 272 | if (!client || !plist || (plist && *plist)) |
| 273 | return LOCKDOWN_E_INVALID_ARG; | 273 | return LOCKDOWN_E_INVALID_ARG; |
| 274 | lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR; | 274 | lockdownd_error_t ret = LOCKDOWN_E_SUCCESS; |
| 275 | char *receive = NULL; | 275 | iphone_error_t err; |
| 276 | uint32_t datalen = 0, bytes = 0, received_bytes = 0; | ||
| 277 | |||
| 278 | if (!client->in_SSL) | ||
| 279 | ret = iphone_device_recv(client->connection, (char *) &datalen, sizeof(datalen), &bytes); | ||
| 280 | else { | ||
| 281 | ssize_t res = gnutls_record_recv(client->ssl_session, &datalen, sizeof(datalen)); | ||
| 282 | if (res < 0) { | ||
| 283 | log_dbg_msg(DBGMASK_LOCKDOWND, "gnutls_record_recv: Error occured: %s\n", gnutls_strerror(res)); | ||
| 284 | return LOCKDOWN_E_SSL_ERROR; | ||
| 285 | } else { | ||
| 286 | bytes = res; | ||
| 287 | ret = LOCKDOWN_E_SUCCESS; | ||
| 288 | } | ||
| 289 | } | ||
| 290 | datalen = ntohl(datalen); | ||
| 291 | log_dbg_msg(DBGMASK_LOCKDOWND, "%s: datalen = %d\n", __func__, datalen); | ||
| 292 | |||
| 293 | receive = (char *) malloc(sizeof(char) * datalen); | ||
| 294 | 276 | ||
| 295 | /* fill buffer and request more packets if needed */ | ||
| 296 | if (!client->in_SSL) { | 277 | if (!client->in_SSL) { |
| 297 | while ((received_bytes < datalen) && (ret == LOCKDOWN_E_SUCCESS)) { | 278 | err = iphone_device_receive_plist(client->connection, plist); |
| 298 | ret = iphone_device_recv(client->connection, receive + received_bytes, datalen - received_bytes, &bytes); | 279 | if (err != IPHONE_E_SUCCESS) { |
| 299 | received_bytes += bytes; | 280 | ret = LOCKDOWN_E_UNKNOWN_ERROR; |
| 300 | } | 281 | } |
| 301 | } else { | 282 | } else { |
| 302 | ssize_t res = 0; | 283 | err = iphone_device_receive_encrypted_plist(client->ssl_session, plist); |
| 303 | while ((received_bytes < datalen) && (ret == LOCKDOWN_E_SUCCESS)) { | 284 | if (err != IPHONE_E_SUCCESS) { |
| 304 | res = gnutls_record_recv(client->ssl_session, receive + received_bytes, datalen - received_bytes); | 285 | return LOCKDOWN_E_SSL_ERROR; |
| 305 | if (res < 0) { | ||
| 306 | log_dbg_msg(DBGMASK_LOCKDOWND, "gnutls_record_recv: Error occured: %s\n", gnutls_strerror(res)); | ||
| 307 | ret = LOCKDOWN_E_SSL_ERROR; | ||
| 308 | } else { | ||
| 309 | received_bytes += res; | ||
| 310 | ret = LOCKDOWN_E_SUCCESS; | ||
| 311 | } | ||
| 312 | } | 286 | } |
| 313 | } | 287 | } |
| 314 | 288 | ||
| 315 | if (ret != LOCKDOWN_E_SUCCESS) { | ||
| 316 | free(receive); | ||
| 317 | return ret; | ||
| 318 | } | ||
| 319 | |||
| 320 | if ((ssize_t)received_bytes <= 0) { | ||
| 321 | free(receive); | ||
| 322 | return LOCKDOWN_E_NOT_ENOUGH_DATA; | ||
| 323 | } | ||
| 324 | |||
| 325 | log_dbg_msg(DBGMASK_LOCKDOWND, "%s: received msg size: %i, buffer follows:\n%s", __func__, received_bytes, receive); | ||
| 326 | plist_from_xml(receive, received_bytes, plist); | ||
| 327 | free(receive); | ||
| 328 | |||
| 329 | if (!*plist) | 289 | if (!*plist) |
| 330 | ret = LOCKDOWN_E_PLIST_ERROR; | 290 | ret = LOCKDOWN_E_PLIST_ERROR; |
| 331 | 291 | ||
| @@ -346,41 +306,21 @@ lockdownd_error_t lockdownd_send(lockdownd_client_t client, plist_t plist) | |||
| 346 | { | 306 | { |
| 347 | if (!client || !plist) | 307 | if (!client || !plist) |
| 348 | return LOCKDOWN_E_INVALID_ARG; | 308 | return LOCKDOWN_E_INVALID_ARG; |
| 349 | char *real_query; | ||
| 350 | int bytes; | ||
| 351 | char *XMLContent = NULL; | ||
| 352 | uint32_t length = 0; | ||
| 353 | lockdownd_error_t ret = LOCKDOWN_E_UNKNOWN_ERROR; | ||
| 354 | 309 | ||
| 355 | plist_to_xml(plist, &XMLContent, &length); | 310 | lockdownd_error_t ret = LOCKDOWN_E_SUCCESS; |
| 356 | log_dbg_msg(DBGMASK_LOCKDOWND, "%s: sending msg size %i, buffer follows:\n%s", __func__, length, XMLContent); | 311 | iphone_error_t err; |
| 357 | 312 | ||
| 358 | real_query = (char *) malloc(sizeof(char) * (length + 4)); | 313 | if (!client->in_SSL) { |
| 359 | length = htonl(length); | 314 | err = iphone_device_send_xml_plist(client->connection, plist); |
| 360 | memcpy(real_query, &length, sizeof(length)); | 315 | if (err != IPHONE_E_SUCCESS) { |
| 361 | memcpy(real_query + 4, XMLContent, ntohl(length)); | 316 | ret = LOCKDOWN_E_UNKNOWN_ERROR; |
| 362 | free(XMLContent); | ||
| 363 | log_dbg_msg(DBGMASK_LOCKDOWND, "%s: made the query, sending it along\n", __func__); | ||
| 364 | |||
| 365 | if (!client->in_SSL) | ||
| 366 | ret = iphone_device_send(client->connection, real_query, ntohl(length) + sizeof(length), (uint32_t*)&bytes); | ||
| 367 | else { | ||
| 368 | ssize_t res = gnutls_record_send(client->ssl_session, real_query, ntohl(length) + sizeof(length)); | ||
| 369 | if (res < 0) { | ||
| 370 | log_dbg_msg(DBGMASK_LOCKDOWND, "gnutls_record_send: Error occured: %s\n", gnutls_strerror(res)); | ||
| 371 | ret = LOCKDOWN_E_SSL_ERROR; | ||
| 372 | } else { | ||
| 373 | bytes = res; | ||
| 374 | ret = LOCKDOWN_E_SUCCESS; | ||
| 375 | } | 317 | } |
| 376 | } | ||
| 377 | if (ret == LOCKDOWN_E_SUCCESS) { | ||
| 378 | log_dbg_msg(DBGMASK_LOCKDOWND, "%s: sent it!\n", __func__); | ||
| 379 | } else { | 318 | } else { |
| 380 | log_dbg_msg(DBGMASK_LOCKDOWND, "%s: sending failed!\n", __func__); | 319 | err = iphone_device_send_encrypted_xml_plist(client->ssl_session, plist); |
| 320 | if (err != IPHONE_E_SUCCESS) { | ||
| 321 | ret = LOCKDOWN_E_SSL_ERROR; | ||
| 322 | } | ||
| 381 | } | 323 | } |
| 382 | free(real_query); | ||
| 383 | |||
| 384 | return ret; | 324 | return ret; |
| 385 | } | 325 | } |
| 386 | 326 | ||
