diff options
| author | 2009-01-08 18:17:21 +0100 | |
|---|---|---|
| committer | 2009-01-09 20:18:38 -0800 | |
| commit | 89ad220b093b73e229207ca2da0ad568d81f69e3 (patch) | |
| tree | babb6c465ad3fd021068f7a86d55845590d06bad /src/lockdown.c | |
| parent | cae85d48c44a9cf9b947a91aef6fbf7309398c4a (diff) | |
| download | libimobiledevice-89ad220b093b73e229207ca2da0ad568d81f69e3.tar.gz libimobiledevice-89ad220b093b73e229207ca2da0ad568d81f69e3.tar.bz2 | |
Perform proper goodby on lockdown shutdown.
Diffstat (limited to 'src/lockdown.c')
| -rw-r--r-- | src/lockdown.c | 178 |
1 files changed, 172 insertions, 6 deletions
diff --git a/src/lockdown.c b/src/lockdown.c index cf0d99e..ab168a3 100644 --- a/src/lockdown.c +++ b/src/lockdown.c | |||
| @@ -92,6 +92,97 @@ iphone_lckd_client_t new_lockdownd_client(iphone_device_t phone) | |||
| 92 | return control; | 92 | return control; |
| 93 | } | 93 | } |
| 94 | 94 | ||
| 95 | /** | ||
| 96 | * Closes the lockdownd communication session, by sending | ||
| 97 | * the StopSession Request to the device. | ||
| 98 | * | ||
| 99 | * @param control The lockdown client | ||
| 100 | */ | ||
| 101 | static void iphone_lckd_stop_session(iphone_lckd_client_t control) | ||
| 102 | { | ||
| 103 | if (!control) | ||
| 104 | return; // IPHONE_E_INVALID_ARG; | ||
| 105 | xmlDocPtr plist = new_plist(); | ||
| 106 | xmlNode *dict, *key; | ||
| 107 | char **dictionary; | ||
| 108 | int bytes = 0, i = 0; | ||
| 109 | iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; | ||
| 110 | |||
| 111 | log_debug_msg("lockdownd_stop_session() called\n"); | ||
| 112 | dict = add_child_to_plist(plist, "dict", "\n", NULL, 0); | ||
| 113 | key = add_key_str_dict_element(plist, dict, "Request", "StopSession", 1); | ||
| 114 | key = add_key_str_dict_element(plist, dict, "SessionID", control->session_id, 1); | ||
| 115 | |||
| 116 | char *XML_content; | ||
| 117 | uint32 length; | ||
| 118 | |||
| 119 | xmlDocDumpMemory(plist, (xmlChar **) & XML_content, &length); | ||
| 120 | ret = iphone_lckd_send(control, XML_content, length, &bytes); | ||
| 121 | |||
| 122 | xmlFree(XML_content); | ||
| 123 | xmlFreeDoc(plist); | ||
| 124 | plist = NULL; | ||
| 125 | ret = iphone_lckd_recv(control, &XML_content, &bytes); | ||
| 126 | |||
| 127 | plist = xmlReadMemory(XML_content, bytes, NULL, NULL, 0); | ||
| 128 | if (!plist) { | ||
| 129 | fprintf(stderr, "lockdownd_stop_session(): IPHONE_E_PLIST_ERROR\n"); | ||
| 130 | return; //IPHONE_E_PLIST_ERROR; | ||
| 131 | } | ||
| 132 | dict = xmlDocGetRootElement(plist); | ||
| 133 | for (dict = dict->children; dict; dict = dict->next) { | ||
| 134 | if (!xmlStrcmp(dict->name, "dict")) | ||
| 135 | break; | ||
| 136 | } | ||
| 137 | if (!dict) { | ||
| 138 | fprintf(stderr, "lockdownd_stop_session(): IPHONE_E_DICT_ERROR\n"); | ||
| 139 | return; //IPHONE_E_DICT_ERROR; | ||
| 140 | } | ||
| 141 | dictionary = read_dict_element_strings(dict); | ||
| 142 | xmlFreeDoc(plist); | ||
| 143 | free(XML_content); | ||
| 144 | |||
| 145 | for (i = 0; dictionary[i]; i += 2) { | ||
| 146 | if (!strcmp(dictionary[i], "Result") && !strcmp(dictionary[i + 1], "Success")) { | ||
| 147 | log_debug_msg("lockdownd_stop_session(): success\n"); | ||
| 148 | ret = IPHONE_E_SUCCESS; | ||
| 149 | break; | ||
| 150 | } | ||
| 151 | } | ||
| 152 | |||
| 153 | free_dictionary(dictionary); | ||
| 154 | return; //ret; | ||
| 155 | } | ||
| 156 | |||
| 157 | /** | ||
| 158 | * Shuts down the SSL session by first calling iphone_lckd_stop_session | ||
| 159 | * to cleanly close the lockdownd communication session, and then | ||
| 160 | * performing a close notify, which is done by "gnutls_bye". | ||
| 161 | * | ||
| 162 | * @param client The lockdown client | ||
| 163 | */ | ||
| 164 | static void iphone_lckd_stop_SSL_session(iphone_lckd_client_t client) | ||
| 165 | { | ||
| 166 | if (!client) { | ||
| 167 | log_debug_msg("lockdownd_stop_SSL_session(): invalid argument!\n"); | ||
| 168 | return; | ||
| 169 | } | ||
| 170 | |||
| 171 | if (client->in_SSL) { | ||
| 172 | log_debug_msg("Stopping SSL Session\n"); | ||
| 173 | iphone_lckd_stop_session(client); | ||
| 174 | log_debug_msg("Sending SSL close notify\n"); | ||
| 175 | gnutls_bye(*client->ssl_session, GNUTLS_SHUT_RDWR); | ||
| 176 | } | ||
| 177 | if (client->ssl_session) { | ||
| 178 | gnutls_deinit(*client->ssl_session); | ||
| 179 | free(client->ssl_session); | ||
| 180 | } | ||
| 181 | client->in_SSL = 0; | ||
| 182 | client->gtls_buffer_hack_len = 0; // dunno if required?! | ||
| 183 | |||
| 184 | return; | ||
| 185 | } | ||
| 95 | 186 | ||
| 96 | /** Closes the lockdownd client and does the necessary housekeeping. | 187 | /** Closes the lockdownd client and does the necessary housekeeping. |
| 97 | * | 188 | * |
| @@ -103,13 +194,17 @@ iphone_error_t iphone_lckd_free_client(iphone_lckd_client_t client) | |||
| 103 | return IPHONE_E_INVALID_ARG; | 194 | return IPHONE_E_INVALID_ARG; |
| 104 | iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; | 195 | iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; |
| 105 | 196 | ||
| 197 | iphone_lckd_stop_SSL_session(client); | ||
| 198 | |||
| 106 | if (client->connection) { | 199 | if (client->connection) { |
| 200 | lockdownd_close(client); | ||
| 201 | |||
| 202 | // IMO, read of final "sessionUpcall connection closed" packet | ||
| 203 | // should come here instead of in iphone_free_device | ||
| 204 | |||
| 107 | ret = iphone_mux_free_client(client->connection); | 205 | ret = iphone_mux_free_client(client->connection); |
| 108 | } | 206 | } |
| 109 | 207 | ||
| 110 | if (client->ssl_session) | ||
| 111 | gnutls_deinit(*client->ssl_session); | ||
| 112 | free(client->ssl_session); | ||
| 113 | free(client); | 208 | free(client); |
| 114 | return ret; | 209 | return ret; |
| 115 | } | 210 | } |
| @@ -520,6 +615,66 @@ iphone_error_t lockdownd_pair_device(iphone_lckd_client_t control, char *uid, ch | |||
| 520 | return ret; | 615 | return ret; |
| 521 | } | 616 | } |
| 522 | 617 | ||
| 618 | /** | ||
| 619 | * Performs the Goodbye Request to tell the device the communication | ||
| 620 | * session is now closed. | ||
| 621 | * | ||
| 622 | * @param control The lockdown client | ||
| 623 | */ | ||
| 624 | void lockdownd_close(iphone_lckd_client_t control) | ||
| 625 | { | ||
| 626 | if (!control) | ||
| 627 | return; // IPHONE_E_INVALID_ARG; | ||
| 628 | xmlDocPtr plist = new_plist(); | ||
| 629 | xmlNode *dict, *key; | ||
| 630 | char **dictionary; | ||
| 631 | int bytes = 0, i = 0; | ||
| 632 | iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; | ||
| 633 | |||
| 634 | log_debug_msg("lockdownd_close() called\n"); | ||
| 635 | dict = add_child_to_plist(plist, "dict", "\n", NULL, 0); | ||
| 636 | key = add_key_str_dict_element(plist, dict, "Request", "Goodbye", 1); | ||
| 637 | char *XML_content; | ||
| 638 | uint32 length; | ||
| 639 | |||
| 640 | xmlDocDumpMemory(plist, (xmlChar **) & XML_content, &length); | ||
| 641 | ret = iphone_lckd_send(control, XML_content, length, &bytes); | ||
| 642 | |||
| 643 | xmlFree(XML_content); | ||
| 644 | xmlFreeDoc(plist); | ||
| 645 | plist = NULL; | ||
| 646 | ret = iphone_lckd_recv(control, &XML_content, &bytes); | ||
| 647 | |||
| 648 | plist = xmlReadMemory(XML_content, bytes, NULL, NULL, 0); | ||
| 649 | if (!plist) { | ||
| 650 | fprintf(stderr, "lockdownd_close(): IPHONE_E_PLIST_ERROR\n"); | ||
| 651 | return; //IPHONE_E_PLIST_ERROR; | ||
| 652 | } | ||
| 653 | dict = xmlDocGetRootElement(plist); | ||
| 654 | for (dict = dict->children; dict; dict = dict->next) { | ||
| 655 | if (!xmlStrcmp(dict->name, "dict")) | ||
| 656 | break; | ||
| 657 | } | ||
| 658 | if (!dict) { | ||
| 659 | fprintf(stderr, "lockdownd_close(): IPHONE_E_DICT_ERROR\n"); | ||
| 660 | return; //IPHONE_E_DICT_ERROR; | ||
| 661 | } | ||
| 662 | dictionary = read_dict_element_strings(dict); | ||
| 663 | xmlFreeDoc(plist); | ||
| 664 | free(XML_content); | ||
| 665 | |||
| 666 | for (i = 0; dictionary[i]; i += 2) { | ||
| 667 | if (!strcmp(dictionary[i], "Result") && !strcmp(dictionary[i + 1], "Success")) { | ||
| 668 | log_debug_msg("lockdownd_close(): success\n"); | ||
| 669 | ret = IPHONE_E_SUCCESS; | ||
| 670 | break; | ||
| 671 | } | ||
| 672 | } | ||
| 673 | |||
| 674 | free_dictionary(dictionary); | ||
| 675 | return; //ret; | ||
| 676 | } | ||
| 677 | |||
| 523 | /** Generates the device certificate from the public key as well as the host | 678 | /** Generates the device certificate from the public key as well as the host |
| 524 | * and root certificates. | 679 | * and root certificates. |
| 525 | * | 680 | * |
| @@ -664,6 +819,8 @@ iphone_error_t lockdownd_start_SSL_session(iphone_lckd_client_t control, const c | |||
| 664 | iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; | 819 | iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; |
| 665 | // end variables | 820 | // end variables |
| 666 | 821 | ||
| 822 | control->session_id[0] = '\0'; | ||
| 823 | |||
| 667 | key = add_key_str_dict_element(plist, dict, "HostID", HostID, 1); | 824 | key = add_key_str_dict_element(plist, dict, "HostID", HostID, 1); |
| 668 | if (!key) { | 825 | if (!key) { |
| 669 | log_debug_msg("Couldn't add a key.\n"); | 826 | log_debug_msg("Couldn't add a key.\n"); |
| @@ -699,6 +856,7 @@ iphone_error_t lockdownd_start_SSL_session(iphone_lckd_client_t control, const c | |||
| 699 | dictionary = read_dict_element_strings(dict); | 856 | dictionary = read_dict_element_strings(dict); |
| 700 | xmlFreeDoc(plist); | 857 | xmlFreeDoc(plist); |
| 701 | free(what2send); | 858 | free(what2send); |
| 859 | ret = IPHONE_E_SSL_ERROR; | ||
| 702 | for (i = 0; dictionary[i]; i += 2) { | 860 | for (i = 0; dictionary[i]; i += 2) { |
| 703 | if (!strcmp(dictionary[i], "Result") && !strcmp(dictionary[i + 1], "Success")) { | 861 | if (!strcmp(dictionary[i], "Result") && !strcmp(dictionary[i + 1], "Success")) { |
| 704 | // Set up GnuTLS... | 862 | // Set up GnuTLS... |
| @@ -741,8 +899,6 @@ iphone_error_t lockdownd_start_SSL_session(iphone_lckd_client_t control, const c | |||
| 741 | return_me = gnutls_handshake(*control->ssl_session); | 899 | return_me = gnutls_handshake(*control->ssl_session); |
| 742 | log_debug_msg("GnuTLS handshake done...\n"); | 900 | log_debug_msg("GnuTLS handshake done...\n"); |
| 743 | 901 | ||
| 744 | free_dictionary(dictionary); | ||
| 745 | |||
| 746 | if (return_me != GNUTLS_E_SUCCESS) { | 902 | if (return_me != GNUTLS_E_SUCCESS) { |
| 747 | log_debug_msg("GnuTLS reported something wrong.\n"); | 903 | log_debug_msg("GnuTLS reported something wrong.\n"); |
| 748 | gnutls_perror(return_me); | 904 | gnutls_perror(return_me); |
| @@ -750,10 +906,20 @@ iphone_error_t lockdownd_start_SSL_session(iphone_lckd_client_t control, const c | |||
| 750 | return IPHONE_E_SSL_ERROR; | 906 | return IPHONE_E_SSL_ERROR; |
| 751 | } else { | 907 | } else { |
| 752 | control->in_SSL = 1; | 908 | control->in_SSL = 1; |
| 753 | return IPHONE_E_SUCCESS; | 909 | ret = IPHONE_E_SUCCESS; |
| 754 | } | 910 | } |
| 911 | } else if (!strcmp(dictionary[i], "SessionID")) { | ||
| 912 | // we need to store the session ID for StopSession | ||
| 913 | strcpy(control->session_id, dictionary[i + 1]); | ||
| 914 | log_debug_msg("SessionID: %s\n", control->session_id); | ||
| 915 | free_dictionary(dictionary); | ||
| 916 | return ret; | ||
| 755 | } | 917 | } |
| 756 | } | 918 | } |
| 919 | if (ret == IPHONE_E_SUCCESS) { | ||
| 920 | log_debug_msg("Failed to get SessionID!\n"); | ||
| 921 | return ret; | ||
| 922 | } | ||
| 757 | 923 | ||
| 758 | log_debug_msg("Apparently failed negotiating with lockdownd.\n"); | 924 | log_debug_msg("Apparently failed negotiating with lockdownd.\n"); |
| 759 | log_debug_msg("Responding dictionary: \n"); | 925 | log_debug_msg("Responding dictionary: \n"); |
