diff options
Diffstat (limited to 'src/lockdown.c')
| -rw-r--r-- | src/lockdown.c | 201 |
1 files changed, 195 insertions, 6 deletions
diff --git a/src/lockdown.c b/src/lockdown.c index c6d5f80..872b7b0 100644 --- a/src/lockdown.c +++ b/src/lockdown.c | |||
| @@ -65,6 +65,104 @@ iphone_lckd_client_t new_lockdownd_client(iphone_device_t phone) | |||
| 65 | return control; | 65 | return control; |
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | /** | ||
| 69 | * Closes the lockdownd communication session, by sending | ||
| 70 | * the StopSession Request to the device. | ||
| 71 | * | ||
| 72 | * @param control The lockdown client | ||
| 73 | */ | ||
| 74 | static void iphone_lckd_stop_session(iphone_lckd_client_t control) | ||
| 75 | { | ||
| 76 | if (!control) | ||
| 77 | return; //IPHONE_E_INVALID_ARG; | ||
| 78 | |||
| 79 | int bytes = 0, i = 0; | ||
| 80 | iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; | ||
| 81 | |||
| 82 | plist_t dict = plist_new_dict(); | ||
| 83 | plist_add_sub_element(dict, PLIST_KEY, (void *) "Request", strlen("Request")); | ||
| 84 | plist_add_sub_element(dict, PLIST_STRING, (void *) "StopSession", strlen("StopSession")); | ||
| 85 | plist_add_sub_element(dict, PLIST_KEY, (void *) "SessionID", strlen("SessionID")); | ||
| 86 | plist_add_sub_element(dict, PLIST_STRING, (void *) control->session_id, strlen(control->session_id)); | ||
| 87 | |||
| 88 | log_debug_msg("iphone_lckd_stop_session() called\n"); | ||
| 89 | char *XML_content = NULL; | ||
| 90 | uint32_t length = 0; | ||
| 91 | |||
| 92 | plist_to_xml(dict, &XML_content, &length); | ||
| 93 | log_debug_msg("Send msg :\nsize : %i\nxml : %s", length, XML_content); | ||
| 94 | ret = iphone_lckd_send(control, XML_content, length, &bytes); | ||
| 95 | |||
| 96 | free(XML_content); | ||
| 97 | XML_content = NULL; | ||
| 98 | plist_free(dict); | ||
| 99 | dict = NULL; | ||
| 100 | |||
| 101 | ret = iphone_lckd_recv(control, &XML_content, &bytes); | ||
| 102 | log_debug_msg("Receive msg :\nsize : %i\nxml : %s", bytes, XML_content); | ||
| 103 | plist_from_xml(XML_content, bytes, &dict); | ||
| 104 | |||
| 105 | if (!dict) { | ||
| 106 | log_debug_msg("lockdownd_stop_session(): IPHONE_E_PLIST_ERROR\n"); | ||
| 107 | return; // IPHONE_E_PLIST_ERROR; | ||
| 108 | } | ||
| 109 | |||
| 110 | plist_t query_node = plist_find_node(dict, PLIST_STRING, "StopSession", strlen("StopSession")); | ||
| 111 | plist_t result_node = plist_get_next_sibling(query_node); | ||
| 112 | plist_t value_node = plist_get_next_sibling(result_node); | ||
| 113 | |||
| 114 | plist_type result_type; | ||
| 115 | plist_type value_type; | ||
| 116 | |||
| 117 | char *result_value = NULL; | ||
| 118 | char *value_value = NULL; | ||
| 119 | uint64_t result_length = 0; | ||
| 120 | uint64_t value_length = 0; | ||
| 121 | |||
| 122 | plist_get_type_and_value(result_node, &result_type, (void *) (&result_value), &result_length); | ||
| 123 | plist_get_type_and_value(value_node, &value_type, (void *) (&value_value), &value_length); | ||
| 124 | |||
| 125 | if (result_type == PLIST_KEY && | ||
| 126 | value_type == PLIST_STRING && !strcmp(result_value, "Result") && !strcmp(value_value, "Success")) { | ||
| 127 | log_debug_msg("lockdownd_stop_session(): success\n"); | ||
| 128 | ret = IPHONE_E_SUCCESS; | ||
| 129 | } | ||
| 130 | |||
| 131 | return; // ret; | ||
| 132 | } | ||
| 133 | |||
| 134 | |||
| 135 | /** | ||
| 136 | * Shuts down the SSL session by first calling iphone_lckd_stop_session | ||
| 137 | * to cleanly close the lockdownd communication session, and then | ||
| 138 | * performing a close notify, which is done by "gnutls_bye". | ||
| 139 | * | ||
| 140 | * @param client The lockdown client | ||
| 141 | */ | ||
| 142 | static void iphone_lckd_stop_SSL_session(iphone_lckd_client_t client) | ||
| 143 | { | ||
| 144 | if (!client) { | ||
| 145 | log_debug_msg("lockdownd_stop_SSL_session(): invalid argument!\n"); | ||
| 146 | return; | ||
| 147 | } | ||
| 148 | |||
| 149 | if (client->in_SSL) { | ||
| 150 | log_debug_msg("Stopping SSL Session\n"); | ||
| 151 | iphone_lckd_stop_session(client); | ||
| 152 | log_debug_msg("Sending SSL close notify\n"); | ||
| 153 | gnutls_bye(*client->ssl_session, GNUTLS_SHUT_RDWR); | ||
| 154 | } | ||
| 155 | if (client->ssl_session) { | ||
| 156 | gnutls_deinit(*client->ssl_session); | ||
| 157 | free(client->ssl_session); | ||
| 158 | } | ||
| 159 | client->in_SSL = 0; | ||
| 160 | client->gtls_buffer_hack_len = 0; // dunno if required?! | ||
| 161 | |||
| 162 | return; | ||
| 163 | } | ||
| 164 | |||
| 165 | |||
| 68 | /** Closes the lockdownd client and does the necessary housekeeping. | 166 | /** Closes the lockdownd client and does the necessary housekeeping. |
| 69 | * | 167 | * |
| 70 | * @param control The lockdown client | 168 | * @param control The lockdown client |
| @@ -75,13 +173,17 @@ iphone_error_t iphone_lckd_free_client(iphone_lckd_client_t client) | |||
| 75 | return IPHONE_E_INVALID_ARG; | 173 | return IPHONE_E_INVALID_ARG; |
| 76 | iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; | 174 | iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; |
| 77 | 175 | ||
| 176 | iphone_lckd_stop_SSL_session(client); | ||
| 177 | |||
| 78 | if (client->connection) { | 178 | if (client->connection) { |
| 179 | lockdownd_close(client); | ||
| 180 | |||
| 181 | // IMO, read of final "sessionUpcall connection closed" packet | ||
| 182 | // should come here instead of in iphone_free_device | ||
| 183 | |||
| 79 | ret = iphone_mux_free_client(client->connection); | 184 | ret = iphone_mux_free_client(client->connection); |
| 80 | } | 185 | } |
| 81 | 186 | ||
| 82 | if (client->ssl_session) | ||
| 83 | gnutls_deinit(*client->ssl_session); | ||
| 84 | free(client->ssl_session); | ||
| 85 | free(client); | 187 | free(client); |
| 86 | return ret; | 188 | return ret; |
| 87 | } | 189 | } |
| @@ -512,6 +614,70 @@ iphone_error_t lockdownd_pair_device(iphone_lckd_client_t control, char *uid, ch | |||
| 512 | return ret; | 614 | return ret; |
| 513 | } | 615 | } |
| 514 | 616 | ||
| 617 | /** | ||
| 618 | * Performs the Goodbye Request to tell the device the communication | ||
| 619 | * session is now closed. | ||
| 620 | * | ||
| 621 | * @param control The lockdown client | ||
| 622 | */ | ||
| 623 | void lockdownd_close(iphone_lckd_client_t control) | ||
| 624 | { | ||
| 625 | if (!control) | ||
| 626 | return; //IPHONE_E_INVALID_ARG; | ||
| 627 | |||
| 628 | int bytes = 0, i = 0; | ||
| 629 | iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; | ||
| 630 | |||
| 631 | plist_t dict = plist_new_dict(); | ||
| 632 | plist_add_sub_element(dict, PLIST_KEY, (void *) "Request", strlen("Request")); | ||
| 633 | plist_add_sub_element(dict, PLIST_STRING, (void *) "Goodbye", strlen("Goodbye")); | ||
| 634 | |||
| 635 | log_debug_msg("lockdownd_close() called\n"); | ||
| 636 | char *XML_content = NULL; | ||
| 637 | uint32_t length = 0; | ||
| 638 | |||
| 639 | plist_to_xml(dict, &XML_content, &length); | ||
| 640 | log_debug_msg("Send msg :\nsize : %i\nxml : %s", length, XML_content); | ||
| 641 | ret = iphone_lckd_send(control, XML_content, length, &bytes); | ||
| 642 | |||
| 643 | free(XML_content); | ||
| 644 | XML_content = NULL; | ||
| 645 | plist_free(dict); | ||
| 646 | dict = NULL; | ||
| 647 | |||
| 648 | ret = iphone_lckd_recv(control, &XML_content, &bytes); | ||
| 649 | log_debug_msg("Receive msg :\nsize : %i\nxml : %s", bytes, XML_content); | ||
| 650 | plist_from_xml(XML_content, bytes, &dict); | ||
| 651 | |||
| 652 | if (!dict) { | ||
| 653 | log_debug_msg("lockdownd_close(): IPHONE_E_PLIST_ERROR\n"); | ||
| 654 | return; // IPHONE_E_PLIST_ERROR; | ||
| 655 | } | ||
| 656 | |||
| 657 | plist_t query_node = plist_find_node(dict, PLIST_STRING, "Goodbye", strlen("Goodbye")); | ||
| 658 | plist_t result_node = plist_get_next_sibling(query_node); | ||
| 659 | plist_t value_node = plist_get_next_sibling(result_node); | ||
| 660 | |||
| 661 | plist_type result_type; | ||
| 662 | plist_type value_type; | ||
| 663 | |||
| 664 | char *result_value = NULL; | ||
| 665 | char *value_value = NULL; | ||
| 666 | uint64_t result_length = 0; | ||
| 667 | uint64_t value_length = 0; | ||
| 668 | |||
| 669 | plist_get_type_and_value(result_node, &result_type, (void *) (&result_value), &result_length); | ||
| 670 | plist_get_type_and_value(value_node, &value_type, (void *) (&value_value), &value_length); | ||
| 671 | |||
| 672 | if (result_type == PLIST_KEY && | ||
| 673 | value_type == PLIST_STRING && !strcmp(result_value, "Result") && !strcmp(value_value, "Success")) { | ||
| 674 | log_debug_msg("lockdownd_close(): success\n"); | ||
| 675 | ret = IPHONE_E_SUCCESS; | ||
| 676 | } | ||
| 677 | |||
| 678 | return; // ret; | ||
| 679 | } | ||
| 680 | |||
| 515 | /** Generates the device certificate from the public key as well as the host | 681 | /** Generates the device certificate from the public key as well as the host |
| 516 | * and root certificates. | 682 | * and root certificates. |
| 517 | * | 683 | * |
| @@ -654,6 +820,7 @@ iphone_error_t lockdownd_start_SSL_session(iphone_lckd_client_t control, const c | |||
| 654 | uint32_t length = 0, bytes = 0, return_me = 0; | 820 | uint32_t length = 0, bytes = 0, return_me = 0; |
| 655 | 821 | ||
| 656 | iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; | 822 | iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; |
| 823 | control->session_id[0] = '\0'; | ||
| 657 | 824 | ||
| 658 | /* Setup DevicePublicKey request plist */ | 825 | /* Setup DevicePublicKey request plist */ |
| 659 | dict = plist_new_dict(); | 826 | dict = plist_new_dict(); |
| @@ -699,7 +866,7 @@ iphone_error_t lockdownd_start_SSL_session(iphone_lckd_client_t control, const c | |||
| 699 | XML_content = NULL; | 866 | XML_content = NULL; |
| 700 | plist_free(dict); | 867 | plist_free(dict); |
| 701 | dict = NULL; | 868 | dict = NULL; |
| 702 | 869 | ret = IPHONE_E_SSL_ERROR; | |
| 703 | if (result_key_type == PLIST_KEY && | 870 | if (result_key_type == PLIST_KEY && |
| 704 | result_value_type == PLIST_STRING && !strcmp(result_key, "Result") && !strcmp(result_value, "Success")) { | 871 | result_value_type == PLIST_STRING && !strcmp(result_key, "Result") && !strcmp(result_value, "Success")) { |
| 705 | // Set up GnuTLS... | 872 | // Set up GnuTLS... |
| @@ -749,12 +916,34 @@ iphone_error_t lockdownd_start_SSL_session(iphone_lckd_client_t control, const c | |||
| 749 | return IPHONE_E_SSL_ERROR; | 916 | return IPHONE_E_SSL_ERROR; |
| 750 | } else { | 917 | } else { |
| 751 | control->in_SSL = 1; | 918 | control->in_SSL = 1; |
| 752 | return IPHONE_E_SUCCESS; | 919 | ret = IPHONE_E_SUCCESS; |
| 753 | } | 920 | } |
| 754 | } | 921 | } |
| 922 | //store session id | ||
| 923 | plist_t session_node = plist_find_node(dict, PLIST_KEY, "SessionID", strlen("SessionID")); | ||
| 924 | if (session_node) { | ||
| 925 | |||
| 926 | plist_type session_node_val_type; | ||
| 927 | char *session_id = NULL; | ||
| 928 | uint64_t session_id_length = 0; | ||
| 929 | plist_t session_node_val = plist_get_next_sibling(session_node); | ||
| 930 | |||
| 931 | plist_get_type_and_value(session_node_val, &session_node_val_type, (void *) (&session_id), | ||
| 932 | &session_id_length); | ||
| 933 | if (session_node_val_type == PLIST_STRING && session_id_length > 0) { | ||
| 934 | // we need to store the session ID for StopSession | ||
| 935 | strcpy(control->session_id, session_id); | ||
| 936 | log_debug_msg("SessionID: %s\n", control->session_id); | ||
| 937 | return ret; | ||
| 938 | } | ||
| 939 | } | ||
| 940 | |||
| 941 | if (ret == IPHONE_E_SUCCESS) { | ||
| 942 | log_debug_msg("Failed to get SessionID!\n"); | ||
| 943 | return ret; | ||
| 944 | } | ||
| 755 | 945 | ||
| 756 | log_debug_msg("Apparently failed negotiating with lockdownd.\n"); | 946 | log_debug_msg("Apparently failed negotiating with lockdownd.\n"); |
| 757 | log_debug_msg("Responding dictionary: \n"); | ||
| 758 | return IPHONE_E_SSL_ERROR; | 947 | return IPHONE_E_SSL_ERROR; |
| 759 | } else { | 948 | } else { |
| 760 | log_debug_msg("Didn't get enough bytes.\n"); | 949 | log_debug_msg("Didn't get enough bytes.\n"); |
