summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGravatar Jonathan Beck2009-01-08 18:51:42 +0100
committerGravatar Jonathan Beck2009-01-08 18:51:42 +0100
commitf53b61c82be8aa6223ab6a524c2287d892f9864c (patch)
tree99f67152a644ded15d0bd7cd16664c4eb1eb7c00 /src
parent5514a3b2a9734d311e4f6014585f922e0b748cab (diff)
parentef98ef7211bc6277e9a87349f0405957ab264936 (diff)
downloadlibimobiledevice-f53b61c82be8aa6223ab6a524c2287d892f9864c.tar.gz
libimobiledevice-f53b61c82be8aa6223ab6a524c2287d892f9864c.tar.bz2
Merge branch 'nikias' into plist
Conflicts: src/lockdown.c
Diffstat (limited to 'src')
-rw-r--r--src/iphone.c59
-rw-r--r--src/lockdown.c201
-rw-r--r--src/lockdown.h1
-rw-r--r--src/usbmux.c3
-rw-r--r--src/utils.c32
5 files changed, 282 insertions, 14 deletions
diff --git a/src/iphone.c b/src/iphone.c
index 32d27f6..1f68180 100644
--- a/src/iphone.c
+++ b/src/iphone.c
@@ -28,6 +28,49 @@
28#include <stdlib.h> 28#include <stdlib.h>
29#include <string.h> 29#include <string.h>
30 30
31/**
32 * This function sets the configuration of the given device to 3
33 * and claims the interface 1. If usb_set_configuration fails, it detaches
34 * the kernel driver that blocks the device, and retries configuration.
35 *
36 * @param phone which device to configure
37 */
38static void iphone_config_usb_device(iphone_device_t phone)
39{
40 int ret;
41
42 log_debug_msg("setting configuration... ");
43 ret = usb_set_configuration(phone->device, 3);
44 if (ret != 0) {
45 log_debug_msg("Hm, usb_set_configuration returned %d: %s, trying to fix:\n", ret, strerror(-ret));
46 log_debug_msg("-> detaching kernel driver... ");
47 ret =
48 usb_detach_kernel_driver_np(phone->device,
49 phone->__device->config->interface->altsetting->bInterfaceNumber);
50 if (ret != 0) {
51 log_debug_msg("usb_detach_kernel_driver_np returned %d: %s\n", ret, strerror(-ret));
52 } else {
53 log_debug_msg("done.\n");
54 log_debug_msg("setting configuration again... ");
55 ret = usb_set_configuration(phone->device, 3);
56 if (ret != 0) {
57 log_debug_msg("Error: usb_set_configuration returned %d: %s\n", ret, strerror(-ret));
58 } else {
59 log_debug_msg("done.\n");
60 }
61 }
62 } else {
63 log_debug_msg("done.\n");
64 }
65
66 log_debug_msg("claiming interface... ");
67 ret = usb_claim_interface(phone->device, 1);
68 if (ret != 0) {
69 log_debug_msg("Error: usb_claim_interface returned %d: %s\n", ret, strerror(-ret));
70 } else {
71 log_debug_msg("done.\n");
72 }
73}
31 74
32/** 75/**
33 * Given a USB bus and device number, returns a device handle to the iPhone on 76 * Given a USB bus and device number, returns a device handle to the iPhone on
@@ -73,8 +116,7 @@ static iphone_error_t iphone_get_specific_device(unsigned int bus_n, int dev_n,
73 if (dev->devnum == dev_n) { 116 if (dev->devnum == dev_n) {
74 phone->__device = dev; 117 phone->__device = dev;
75 phone->device = usb_open(phone->__device); 118 phone->device = usb_open(phone->__device);
76 usb_set_configuration(phone->device, 3); 119 iphone_config_usb_device(phone);
77 usb_claim_interface(phone->device, 1);
78 goto found; 120 goto found;
79 } 121 }
80 122
@@ -115,9 +157,10 @@ static iphone_error_t iphone_get_specific_device(unsigned int bus_n, int dev_n,
115 return IPHONE_E_SUCCESS; 157 return IPHONE_E_SUCCESS;
116 } else { 158 } else {
117 // Bad header 159 // Bad header
160 log_debug_msg("get_iPhone(): Received a bad header/invalid version number.\n");
161 log_debug_buffer((char *) version, sizeof(*version));
118 iphone_free_device(phone); 162 iphone_free_device(phone);
119 free(version); 163 free(version);
120 log_debug_msg("get_iPhone(): Received a bad header/invalid version number.");
121 return IPHONE_E_BAD_HEADER; 164 return IPHONE_E_BAD_HEADER;
122 } 165 }
123 166
@@ -173,13 +216,21 @@ iphone_error_t iphone_free_device(iphone_device_t device)
173 if (!device) 216 if (!device)
174 return IPHONE_E_INVALID_ARG; 217 return IPHONE_E_INVALID_ARG;
175 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR; 218 iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
219 int bytes;
220 unsigned char buf[512];
221
222 // read final package
223 bytes = usb_bulk_read(device->device, BULKIN, (void *) &buf, 512, 1000);
224 if (bytes > 0) {
225 log_debug_msg("iphone_free_device: final read returned\n");
226 log_debug_buffer(buf, bytes);
227 }
176 228
177 if (device->buffer) { 229 if (device->buffer) {
178 free(device->buffer); 230 free(device->buffer);
179 } 231 }
180 if (device->device) { 232 if (device->device) {
181 usb_release_interface(device->device, 1); 233 usb_release_interface(device->device, 1);
182 usb_reset(device->device);
183 usb_close(device->device); 234 usb_close(device->device);
184 ret = IPHONE_E_SUCCESS; 235 ret = IPHONE_E_SUCCESS;
185 } 236 }
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 */
74static 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 */
142static 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 */
623void 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");
diff --git a/src/lockdown.h b/src/lockdown.h
index 8ca8a7f..cdc46b8 100644
--- a/src/lockdown.h
+++ b/src/lockdown.h
@@ -37,6 +37,7 @@ struct iphone_lckd_client_int {
37 int in_SSL; 37 int in_SSL;
38 char *gtls_buffer_hack; 38 char *gtls_buffer_hack;
39 int gtls_buffer_hack_len; 39 int gtls_buffer_hack_len;
40 char session_id[40];
40}; 41};
41 42
42iphone_lckd_client_t new_lockdownd_client(iphone_device_t phone); 43iphone_lckd_client_t new_lockdownd_client(iphone_device_t phone);
diff --git a/src/usbmux.c b/src/usbmux.c
index 427b880..eb7ec97 100644
--- a/src/usbmux.c
+++ b/src/usbmux.c
@@ -182,8 +182,11 @@ iphone_error_t iphone_mux_free_client(iphone_umux_client_t client)
182 return IPHONE_E_INVALID_ARG; 182 return IPHONE_E_INVALID_ARG;
183 183
184 client->header->tcp_flags = 0x04; 184 client->header->tcp_flags = 0x04;
185 client->header->length = htonl(0x1C);
185 client->header->scnt = htonl(client->header->scnt); 186 client->header->scnt = htonl(client->header->scnt);
186 client->header->ocnt = htonl(client->header->ocnt); 187 client->header->ocnt = htonl(client->header->ocnt);
188 client->header->window = 0;
189 client->header->length16 = htons(0x1C);
187 int bytes = 0; 190 int bytes = 0;
188 191
189 bytes = usb_bulk_write(client->phone->device, BULKOUT, (char *) client->header, sizeof(usbmux_tcp_header), 800); 192 bytes = usb_bulk_write(client->phone->device, BULKOUT, (char *) client->header, sizeof(usbmux_tcp_header), 800);
diff --git a/src/utils.c b/src/utils.c
index ceb1f5d..fb98471 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -56,11 +56,35 @@ void log_debug_msg(const char *format, ...)
56inline void log_debug_buffer(const char *data, const int length) 56inline void log_debug_buffer(const char *data, const int length)
57{ 57{
58#ifndef STRIP_DEBUG_CODE 58#ifndef STRIP_DEBUG_CODE
59 int i;
60 int j;
61 unsigned char c;
59 62
60 /* run the real fprintf */ 63 if (toto_debug) {
61 if (toto_debug) 64 for (i = 0; i < length; i += 16) {
62 fwrite(data, 1, length, stderr); 65 fprintf(stderr, "%04x: ", i);
63 66 for (j = 0; j < 16; j++) {
67 if (i + j >= length) {
68 fprintf(stderr, " ");
69 continue;
70 }
71 fprintf(stderr, "%02hhx ", *(data + i + j));
72 }
73 fprintf(stderr, " | ");
74 for (j = 0; j < 16; j++) {
75 if (i + j >= length)
76 break;
77 c = *(data + i + j);
78 if ((c < 32) || (c > 127)) {
79 fprintf(stderr, ".");
80 continue;
81 }
82 fprintf(stderr, "%c", c);
83 }
84 fprintf(stderr, "\n");
85 }
86 fprintf(stderr, "\n");
87 }
64#endif 88#endif
65} 89}
66 90