Commit 62bcedce authored by Matt Colyer's avatar Matt Colyer

Zack's C. rewrite of usbmux (with a few additions by Matt Colyer).

parent 294f6080
...@@ -34,7 +34,6 @@ AFClient *afc_connect(iPhone *phone, int s_port, int d_port) { ...@@ -34,7 +34,6 @@ AFClient *afc_connect(iPhone *phone, int s_port, int d_port) {
else { else {
client->afc_packet = (AFCPacket*)malloc(sizeof(AFCPacket)); client->afc_packet = (AFCPacket*)malloc(sizeof(AFCPacket));
if (client->afc_packet) { if (client->afc_packet) {
client->phone = phone;
client->afc_packet->packet_num = 0; client->afc_packet->packet_num = 0;
client->afc_packet->unknown1 = client->afc_packet->unknown2 = client->afc_packet->unknown3 = client->afc_packet->unknown4 = client->afc_packet->entire_length = client->afc_packet->this_length = 0; client->afc_packet->unknown1 = client->afc_packet->unknown2 = client->afc_packet->unknown3 = client->afc_packet->unknown4 = client->afc_packet->entire_length = client->afc_packet->this_length = 0;
client->afc_packet->header1 = 0x36414643; client->afc_packet->header1 = 0x36414643;
...@@ -42,7 +41,7 @@ AFClient *afc_connect(iPhone *phone, int s_port, int d_port) { ...@@ -42,7 +41,7 @@ AFClient *afc_connect(iPhone *phone, int s_port, int d_port) {
client->file_handle = 0; client->file_handle = 0;
return client; return client;
} else { } else {
mux_close_connection(client->phone, client->connection); mux_close_connection(client->connection);
free(client); free(client);
return NULL; return NULL;
} }
...@@ -53,8 +52,8 @@ AFClient *afc_connect(iPhone *phone, int s_port, int d_port) { ...@@ -53,8 +52,8 @@ AFClient *afc_connect(iPhone *phone, int s_port, int d_port) {
void afc_disconnect(AFClient *client) { void afc_disconnect(AFClient *client) {
// client and its members should never be NULL is assumed here. // client and its members should never be NULL is assumed here.
if (!client || !client->connection || !client->phone || !client->afc_packet) return; if (!client || !client->connection || !client->afc_packet) return;
mux_close_connection(client->phone, client->connection); mux_close_connection(client->connection);
free(client->afc_packet); free(client->afc_packet);
free(client); free(client);
} }
...@@ -67,10 +66,10 @@ int count_nullspaces(char *string, int number) { ...@@ -67,10 +66,10 @@ int count_nullspaces(char *string, int number) {
return nulls; return nulls;
} }
int dispatch_AFC_packet(AFClient *client, char *data, int length) { int dispatch_AFC_packet(AFClient *client, const char *data, int length) {
char *buffer; char *buffer;
int bytes = 0, offset = 0; int bytes = 0, offset = 0;
if (!client || !client->connection || !client->phone || !client->afc_packet) return 0; if (!client || !client->connection || !client->afc_packet) return 0;
if (!data || !length) length = 0; if (!data || !length) length = 0;
client->afc_packet->packet_num++; client->afc_packet->packet_num++;
...@@ -91,7 +90,7 @@ int dispatch_AFC_packet(AFClient *client, char *data, int length) { ...@@ -91,7 +90,7 @@ int dispatch_AFC_packet(AFClient *client, char *data, int length) {
} }
if (debug) printf("dispatch_AFC_packet: fucked-up packet method (probably a write)\n"); if (debug) printf("dispatch_AFC_packet: fucked-up packet method (probably a write)\n");
memcpy(buffer+sizeof(AFCPacket), data, offset); memcpy(buffer+sizeof(AFCPacket), data, offset);
bytes = mux_send(client->phone, client->connection, buffer, client->afc_packet->this_length); bytes = mux_send(client->connection, buffer, client->afc_packet->this_length);
free(buffer); free(buffer);
if (bytes <= 0) { return 0; } if (bytes <= 0) { return 0; }
if (debug) { if (debug) {
...@@ -102,7 +101,7 @@ int dispatch_AFC_packet(AFClient *client, char *data, int length) { ...@@ -102,7 +101,7 @@ int dispatch_AFC_packet(AFClient *client, char *data, int length) {
} }
bytes = mux_send(client->phone, client->connection, data+offset, length-offset); bytes = mux_send(client->connection, data+offset, length-offset);
if (bytes <= 0) { return 0; } if (bytes <= 0) { return 0; }
else { return bytes; } else { return bytes; }
} else { } else {
...@@ -114,7 +113,7 @@ int dispatch_AFC_packet(AFClient *client, char *data, int length) { ...@@ -114,7 +113,7 @@ int dispatch_AFC_packet(AFClient *client, char *data, int length) {
if (length > 0) { memcpy(buffer+sizeof(AFCPacket), data, length); buffer[sizeof(AFCPacket)+length] = '\0'; } if (length > 0) { memcpy(buffer+sizeof(AFCPacket), data, length); buffer[sizeof(AFCPacket)+length] = '\0'; }
if (debug) fwrite(buffer, 1, client->afc_packet->this_length, stdout); if (debug) fwrite(buffer, 1, client->afc_packet->this_length, stdout);
if (debug) printf("\n"); if (debug) printf("\n");
bytes = mux_send(client->phone, client->connection, buffer, client->afc_packet->this_length); bytes = mux_send(client->connection, buffer, client->afc_packet->this_length);
if (bytes <= 0) return 0; if (bytes <= 0) return 0;
else return bytes; else return bytes;
} }
...@@ -128,7 +127,7 @@ int receive_AFC_data(AFClient *client, char **dump_here) { ...@@ -128,7 +127,7 @@ int receive_AFC_data(AFClient *client, char **dump_here) {
int bytes = 0, recv_len = 0, current_count=0; int bytes = 0, recv_len = 0, current_count=0;
int retval = 0; int retval = 0;
bytes = mux_recv(client->phone, client->connection, buffer, sizeof(AFCPacket) * 4); bytes = mux_recv(client->connection, buffer, sizeof(AFCPacket) * 4);
if (bytes <= 0) { if (bytes <= 0) {
free(buffer); free(buffer);
printf("Just didn't get enough.\n"); printf("Just didn't get enough.\n");
...@@ -151,10 +150,17 @@ int receive_AFC_data(AFClient *client, char **dump_here) { ...@@ -151,10 +150,17 @@ int receive_AFC_data(AFClient *client, char **dump_here) {
uint32 param1 = buffer[sizeof(AFCPacket)]; uint32 param1 = buffer[sizeof(AFCPacket)];
free(buffer); free(buffer);
if (r_packet->operation == 0x01 && !((client->afc_packet->operation == AFC_DELETE && param1 == 7))) { if (r_packet->operation == AFC_ERROR
if (debug) printf("Oops? Bad operation code received: 0x%0X\n", r_packet->operation); && !(client->afc_packet->operation == AFC_DELETE && param1 == 7)
if (param1 == 0) { )
{
if (debug) printf("Oops? Bad operation code received: 0x%X, operation=0x%X, param1=%d\n",
r_packet->operation, client->afc_packet->operation, param1);
recv_len = r_packet->entire_length - r_packet->this_length;
if (debug) printf("recv_len=%d\n", recv_len);
if(param1 == 0) {
if (debug) printf("... false alarm, but still\n"); if (debug) printf("... false alarm, but still\n");
*dump_here = NULL;
return 1; return 1;
} }
else { if (debug) printf("Errno %i\n", param1); } else { if (debug) printf("Errno %i\n", param1); }
...@@ -167,13 +173,17 @@ int receive_AFC_data(AFClient *client, char **dump_here) { ...@@ -167,13 +173,17 @@ int receive_AFC_data(AFClient *client, char **dump_here) {
recv_len = r_packet->entire_length - r_packet->this_length; recv_len = r_packet->entire_length - r_packet->this_length;
free(r_packet); free(r_packet);
if (!recv_len) return bytes; if (!recv_len)
{
*dump_here = NULL;
return 0;
}
// Keep collecting packets until we have received the entire file. // Keep collecting packets until we have received the entire file.
buffer = (char*)malloc(sizeof(char) * (recv_len < MAXIMUM_PACKET_SIZE) ? recv_len : MAXIMUM_PACKET_SIZE); buffer = (char*)malloc(sizeof(char) * (recv_len < MAXIMUM_PACKET_SIZE) ? recv_len : MAXIMUM_PACKET_SIZE);
final_buffer = (char*)malloc(sizeof(char) * recv_len); final_buffer = (char*)malloc(sizeof(char) * recv_len);
while(current_count < recv_len){ while(current_count < recv_len){
bytes = mux_recv(client->phone, client->connection, buffer, recv_len-current_count); bytes = mux_recv(client->connection, buffer, recv_len-current_count);
if (bytes < 0) if (bytes < 0)
{ {
if(debug) printf("receive_AFC_data: mux_recv failed: %d\n", bytes); if(debug) printf("receive_AFC_data: mux_recv failed: %d\n", bytes);
...@@ -200,7 +210,7 @@ int receive_AFC_data(AFClient *client, char **dump_here) { ...@@ -200,7 +210,7 @@ int receive_AFC_data(AFClient *client, char **dump_here) {
return current_count; return current_count;
} }
char **afc_get_dir_list(AFClient *client, char *dir) { char **afc_get_dir_list(AFClient *client, const char *dir) {
client->afc_packet->operation = AFC_LIST_DIR; client->afc_packet->operation = AFC_LIST_DIR;
int bytes = 0; int bytes = 0;
char *blah = NULL, **list = NULL; char *blah = NULL, **list = NULL;
...@@ -232,7 +242,7 @@ char **make_strings_list(char *tokens, int true_length) { ...@@ -232,7 +242,7 @@ char **make_strings_list(char *tokens, int true_length) {
} }
int afc_delete_file(AFClient *client, const char *path) { int afc_delete_file(AFClient *client, const char *path) {
if (!client || !path || !client->afc_packet || !client->phone ||!client->connection) return 0; if (!client || !path || !client->afc_packet || !client->connection) return 0;
char *receive = NULL; char *receive = NULL;
client->afc_packet->this_length = client->afc_packet->entire_length = 0; client->afc_packet->this_length = client->afc_packet->entire_length = 0;
...@@ -248,7 +258,7 @@ int afc_delete_file(AFClient *client, const char *path) { ...@@ -248,7 +258,7 @@ int afc_delete_file(AFClient *client, const char *path) {
} }
int afc_rename_file(AFClient *client, const char *from, const char *to) { int afc_rename_file(AFClient *client, const char *from, const char *to) {
if (!client || !from || !to || !client->afc_packet || !client->phone || !client->connection) return 0; if (!client || !from || !to || !client->afc_packet || !client->connection) return 0;
char *receive = NULL; char *receive = NULL;
char *send = (char*)malloc(sizeof(char) * (strlen(from) + strlen(to) + 1 + sizeof(uint32))); char *send = (char*)malloc(sizeof(char) * (strlen(from) + strlen(to) + 1 + sizeof(uint32)));
...@@ -271,7 +281,7 @@ int afc_rename_file(AFClient *client, const char *from, const char *to) { ...@@ -271,7 +281,7 @@ int afc_rename_file(AFClient *client, const char *from, const char *to) {
AFCFile *afc_get_file_info(AFClient *client, char *path) { AFCFile *afc_get_file_info(AFClient *client, const char *path) {
client->afc_packet->operation = AFC_GET_INFO; client->afc_packet->operation = AFC_GET_INFO;
client->afc_packet->entire_length = client->afc_packet->this_length = 0; client->afc_packet->entire_length = client->afc_packet->this_length = 0;
dispatch_AFC_packet(client, path, strlen(path)); dispatch_AFC_packet(client, path, strlen(path));
...@@ -312,7 +322,7 @@ AFCFile *afc_get_file_info(AFClient *client, char *path) { ...@@ -312,7 +322,7 @@ AFCFile *afc_get_file_info(AFClient *client, char *path) {
AFCFile *afc_open_file(AFClient *client, const char *filename, uint32 file_mode) { AFCFile *afc_open_file(AFClient *client, const char *filename, uint32 file_mode) {
if (file_mode != AFC_FILE_READ && file_mode != AFC_FILE_WRITE) return NULL; if (file_mode != AFC_FILE_READ && file_mode != AFC_FILE_WRITE) return NULL;
if (!client ||!client->connection || !client->phone ||!client->afc_packet) return NULL; if (!client ||!client->connection || !client->afc_packet) return NULL;
char *further_data = (char*)malloc(sizeof(char) * (8 + strlen(filename) + 1)); char *further_data = (char*)malloc(sizeof(char) * (8 + strlen(filename) + 1));
AFCFile *file_infos = NULL; AFCFile *file_infos = NULL;
memcpy(further_data, &file_mode, 4); memcpy(further_data, &file_mode, 4);
...@@ -345,7 +355,7 @@ AFCFile *afc_open_file(AFClient *client, const char *filename, uint32 file_mode) ...@@ -345,7 +355,7 @@ AFCFile *afc_open_file(AFClient *client, const char *filename, uint32 file_mode)
} }
int afc_read_file(AFClient *client, AFCFile *file, char *data, int length) { int afc_read_file(AFClient *client, AFCFile *file, char *data, int length) {
if (!client || !client->afc_packet || !client->phone || !client->connection || !file) return -1; if (!client || !client->afc_packet || !client->connection || !file) return -1;
AFCFilePacket *packet = (AFCFilePacket*)malloc(sizeof(AFCFilePacket)); AFCFilePacket *packet = (AFCFilePacket*)malloc(sizeof(AFCFilePacket));
char *input = NULL; char *input = NULL;
packet->unknown1 = packet->unknown2 = 0; packet->unknown1 = packet->unknown2 = 0;
...@@ -359,10 +369,14 @@ int afc_read_file(AFClient *client, AFCFile *file, char *data, int length) { ...@@ -359,10 +369,14 @@ int afc_read_file(AFClient *client, AFCFile *file, char *data, int length) {
if (bytes > 0) { if (bytes > 0) {
bytes = receive_AFC_data(client, &input); bytes = receive_AFC_data(client, &input);
if (bytes <= 0) { if (bytes < 0) {
if (input) free(input); if (input) free(input);
return -1; return -1;
} else if (bytes == 0) {
if (input) free(input);
return 0;
} else { } else {
if (input)
memcpy(data, input, (bytes > length) ? length : bytes); memcpy(data, input, (bytes > length) ? length : bytes);
free(input); free(input);
return (bytes > length) ? length : bytes; return (bytes > length) ? length : bytes;
...@@ -373,9 +387,9 @@ int afc_read_file(AFClient *client, AFCFile *file, char *data, int length) { ...@@ -373,9 +387,9 @@ int afc_read_file(AFClient *client, AFCFile *file, char *data, int length) {
return 0; return 0;
} }
int afc_write_file(AFClient *client, AFCFile *file, char *data, int length) { int afc_write_file(AFClient *client, AFCFile *file, const char *data, int length) {
char *acknowledgement = NULL; char *acknowledgement = NULL;
if (!client ||!client->afc_packet ||!client->phone || !client->connection || !file) return -1; if (!client ||!client->afc_packet || !client->connection || !file) return -1;
client->afc_packet->this_length = sizeof(AFCPacket) + 8; client->afc_packet->this_length = sizeof(AFCPacket) + 8;
client->afc_packet->entire_length = client->afc_packet->this_length + length; client->afc_packet->entire_length = client->afc_packet->this_length + length;
client->afc_packet->operation = AFC_WRITE; client->afc_packet->operation = AFC_WRITE;
......
...@@ -35,8 +35,7 @@ typedef struct { ...@@ -35,8 +35,7 @@ typedef struct {
} AFCPacket; } AFCPacket;
typedef struct { typedef struct {
usbmux_tcp_header *connection; usbmux_connection *connection;
iPhone *phone;
AFCPacket *afc_packet; AFCPacket *afc_packet;
int file_handle; int file_handle;
} AFClient; } AFClient;
...@@ -79,14 +78,14 @@ AFClient *afc_connect(iPhone *phone, int s_port, int d_port); ...@@ -79,14 +78,14 @@ AFClient *afc_connect(iPhone *phone, int s_port, int d_port);
void afc_disconnect(AFClient *client); void afc_disconnect(AFClient *client);
int count_nullspaces(char *string, int number); int count_nullspaces(char *string, int number);
char **make_strings_list(char *tokens, int true_length); char **make_strings_list(char *tokens, int true_length);
int dispatch_AFC_packet(AFClient *client, char *data, int length); int dispatch_AFC_packet(AFClient *client, const char *data, int length);
int receive_AFC_data(AFClient *client, char **dump_here); int receive_AFC_data(AFClient *client, char **dump_here);
char **afc_get_dir_list(AFClient *client, char *dir); char **afc_get_dir_list(AFClient *client, const char *dir);
AFCFile *afc_get_file_info(AFClient *client, char *path); AFCFile *afc_get_file_info(AFClient *client, const char *path);
AFCFile *afc_open_file(AFClient *client, const char *filename, uint32 file_mode); AFCFile *afc_open_file(AFClient *client, const char *filename, uint32 file_mode);
void afc_close_file(AFClient *client, AFCFile *file); void afc_close_file(AFClient *client, AFCFile *file);
int afc_read_file(AFClient *client, AFCFile *file, char *data, int length); int afc_read_file(AFClient *client, AFCFile *file, char *data, int length);
int afc_write_file(AFClient *client, AFCFile *file, char *data, int length); int afc_write_file(AFClient *client, AFCFile *file, const char *data, int length);
int afc_delete_file(AFClient *client, const char *path); int afc_delete_file(AFClient *client, const char *path);
int afc_rename_file(AFClient *client, const char *from, const char *to); int afc_rename_file(AFClient *client, const char *from, const char *to);
...@@ -155,9 +155,10 @@ void *ifuse_init(struct fuse_conn_info *conn) { ...@@ -155,9 +155,10 @@ void *ifuse_init(struct fuse_conn_info *conn) {
return afc; return afc;
} }
void ifuse_cleanup(AFClient *afc) { void ifuse_cleanup(void *data) {
AFClient *afc = (AFClient *)data;
if (afc) { if (afc) {
iPhone *phone = afc->phone; iPhone *phone = afc->connection->phone;
afc_disconnect(afc); afc_disconnect(afc);
free_iPhone(phone); free_iPhone(phone);
} }
......
...@@ -171,10 +171,11 @@ int send_to_phone(iPhone *phone, char *data, int datalen) { ...@@ -171,10 +171,11 @@ int send_to_phone(iPhone *phone, char *data, int datalen) {
int recv_from_phone(iPhone *phone, char *data, int datalen) { int recv_from_phone(iPhone *phone, char *data, int datalen) {
if (!phone) return -1; if (!phone) return -1;
int bytes = 0; int bytes = 0;
if (debug) printf("recv_from_phone(): attempting to receive %i bytes\n", datalen);
bytes = usb_bulk_read(phone->device, BULKIN, data, datalen, 3500); bytes = usb_bulk_read(phone->device, BULKIN, data, datalen, 3500);
if(bytes < 0) if(bytes < 0)
{ {
if(debug) printf("recv_from_iphone(): libusb gave me the error %d: %s (%s)\n", bytes, usb_strerror(), strerror(-bytes)); if(debug) printf("recv_from_phone(): libusb gave me the error %d: %s (%s)\n", bytes, usb_strerror(), strerror(-bytes));
return -1; return -1;
} }
return bytes; return bytes;
......
...@@ -39,7 +39,6 @@ lockdownd_client *new_lockdownd_client(iPhone *phone) { ...@@ -39,7 +39,6 @@ lockdownd_client *new_lockdownd_client(iPhone *phone) {
control->ssl_session = (gnutls_session_t*)malloc(sizeof(gnutls_session_t)); control->ssl_session = (gnutls_session_t*)malloc(sizeof(gnutls_session_t));
control->in_SSL = 0; control->in_SSL = 0;
control->iphone = phone;
control->gtls_buffer_hack_len = 0; control->gtls_buffer_hack_len = 0;
return control; return control;
} }
...@@ -47,7 +46,7 @@ lockdownd_client *new_lockdownd_client(iPhone *phone) { ...@@ -47,7 +46,7 @@ lockdownd_client *new_lockdownd_client(iPhone *phone) {
void lockdown_close(lockdownd_client *control) { void lockdown_close(lockdownd_client *control) {
if (!control) return; if (!control) return;
if (control->connection) { if (control->connection) {
mux_close_connection(control->iphone, control->connection); mux_close_connection(control->connection);
} }
if (control->ssl_session) free(control->ssl_session); if (control->ssl_session) free(control->ssl_session);
...@@ -56,21 +55,23 @@ void lockdown_close(lockdownd_client *control) { ...@@ -56,21 +55,23 @@ void lockdown_close(lockdownd_client *control) {
int lockdownd_recv(lockdownd_client *control, char **dump_data) { int lockdownd_recv(lockdownd_client *control, char **dump_data) {
if (!control) return 0;
char *receive; char *receive;
uint32 datalen = 0, bytes = 0; uint32 datalen = 0, bytes = 0;
if (!control->in_SSL) bytes = mux_recv(control->iphone, control->connection, &datalen, sizeof(datalen)); if (!control->in_SSL) bytes = mux_recv(control->connection, (char *)&datalen, sizeof(datalen));
else bytes = gnutls_record_recv(*control->ssl_session, &datalen, sizeof(datalen)); else bytes = gnutls_record_recv(*control->ssl_session, &datalen, sizeof(datalen));
datalen = ntohl(datalen); datalen = ntohl(datalen);
receive = (char*)malloc(sizeof(char) * datalen); receive = (char*)malloc(sizeof(char) * datalen);
if (!control->in_SSL) bytes = mux_recv(control->iphone, control->connection, receive, datalen); if (!control->in_SSL) bytes = mux_recv(control->connection, receive, datalen);
else bytes = gnutls_record_recv(*control->ssl_session, receive, datalen); else bytes = gnutls_record_recv(*control->ssl_session, receive, datalen);
*dump_data = receive; *dump_data = receive;
return bytes; return bytes;
} }
int lockdownd_send(lockdownd_client *control, char *raw_data, uint32 length) { int lockdownd_send(lockdownd_client *control, char *raw_data, uint32 length) {
if (!control) return 0;
char *real_query; char *real_query;
int bytes; int bytes;
...@@ -78,29 +79,39 @@ int lockdownd_send(lockdownd_client *control, char *raw_data, uint32 length) { ...@@ -78,29 +79,39 @@ int lockdownd_send(lockdownd_client *control, char *raw_data, uint32 length) {
length = htonl(length); length = htonl(length);
memcpy(real_query, &length, sizeof(length)); memcpy(real_query, &length, sizeof(length));
memcpy(real_query+4, raw_data, ntohl(length)); memcpy(real_query+4, raw_data, ntohl(length));
if (!control->in_SSL) bytes = mux_send(control->iphone, control->connection, real_query, ntohl(length)+sizeof(length)); if (debug) {
printf("lockdownd_send(): made the query, sending it along\n");
FILE *packet = fopen("grpkt", "w");
fwrite(real_query, 1, ntohl(length)+4, packet);
fclose(packet);
packet = NULL;
}
if (!control->in_SSL) bytes = mux_send(control->connection, real_query, ntohl(length)+sizeof(length));
else gnutls_record_send(*control->ssl_session, real_query, ntohl(length)+sizeof(length)); else gnutls_record_send(*control->ssl_session, real_query, ntohl(length)+sizeof(length));
if (debug) printf("lockdownd_send(): sent it!\n");
free(real_query);
return bytes; return bytes;
} }
int lockdownd_hello(lockdownd_client *control) { int lockdownd_hello(lockdownd_client *control) {
if (!control) return 0;
xmlDocPtr plist = new_plist(); xmlDocPtr plist = new_plist();
xmlNode *dict, *key; xmlNode *dict, *key;
char **dictionary; char **dictionary;
int bytes = 0, i = 0; int bytes = 0, i = 0;
if (debug) printf("lockdownd_hello() called\n");
dict = add_child_to_plist(plist, "dict", "\n", NULL, 0); dict = add_child_to_plist(plist, "dict", "\n", NULL, 0);
key = add_key_str_dict_element(plist, dict, "Request", "QueryType", 1); key = add_key_str_dict_element(plist, dict, "Request", "QueryType", 1);
char *XML_content; char *XML_content;
uint32 length; uint32 length;
xmlDocDumpMemory(plist, &XML_content, &length); xmlDocDumpMemory(plist, (xmlChar **)&XML_content, &length);
bytes = lockdownd_send(control, XML_content, length); bytes = lockdownd_send(control, XML_content, length);
xmlFree(XML_content); xmlFree(XML_content);
xmlFreeDoc(plist); plist = NULL; xmlFreeDoc(plist); plist = NULL;
bytes = lockdownd_recv(control, &XML_content); bytes = lockdownd_recv(control, &XML_content);
plist = xmlReadMemory(XML_content, bytes, NULL, NULL, 0); plist = xmlReadMemory(XML_content, bytes, NULL, NULL, 0);
...@@ -118,6 +129,7 @@ int lockdownd_hello(lockdownd_client *control) { ...@@ -118,6 +129,7 @@ int lockdownd_hello(lockdownd_client *control) {
for (i = 0; strcmp(dictionary[i], ""); i+=2) { for (i = 0; strcmp(dictionary[i], ""); i+=2) {
if (!strcmp(dictionary[i], "Result") && !strcmp(dictionary[i+1], "Success")) { if (!strcmp(dictionary[i], "Result") && !strcmp(dictionary[i+1], "Success")) {
free_dictionary(dictionary); free_dictionary(dictionary);
if (debug) printf("lockdownd_hello(): success\n");
return 1; return 1;
} }
} }
...@@ -147,7 +159,7 @@ int lockdownd_start_SSL_session(lockdownd_client *control, const char *HostID) { ...@@ -147,7 +159,7 @@ int lockdownd_start_SSL_session(lockdownd_client *control, const char *HostID) {
return 0; return 0;
} }
xmlDocDumpMemory(plist, &what2send, &len); xmlDocDumpMemory(plist, (xmlChar **)&what2send, &len);
bytes = lockdownd_send(control, what2send, len); bytes = lockdownd_send(control, what2send, len);
xmlFree(what2send); xmlFree(what2send);
...@@ -239,7 +251,7 @@ ssize_t lockdownd_secuwrite(gnutls_transport_ptr_t transport, char *buffer, size ...@@ -239,7 +251,7 @@ ssize_t lockdownd_secuwrite(gnutls_transport_ptr_t transport, char *buffer, size
control = (lockdownd_client*)transport; control = (lockdownd_client*)transport;
if (debug) printf("lockdownd_secuwrite() called\n"); if (debug) printf("lockdownd_secuwrite() called\n");
if (debug) printf("pre-send\nlength = %i\n", length); if (debug) printf("pre-send\nlength = %i\n", length);
bytes = mux_send(control->iphone, control->connection, buffer, length); bytes = mux_send(control->connection, buffer, length);
if (debug) printf("post-send\nsent %i bytes\n", bytes); if (debug) printf("post-send\nsent %i bytes\n", bytes);
if (debug) { if (debug) {
FILE *my_ssl_packet = fopen("sslpacketwrite.out", "w+"); FILE *my_ssl_packet = fopen("sslpacketwrite.out", "w+");
...@@ -289,7 +301,7 @@ ssize_t lockdownd_securead(gnutls_transport_ptr_t transport, char *buffer, size_ ...@@ -289,7 +301,7 @@ ssize_t lockdownd_securead(gnutls_transport_ptr_t transport, char *buffer, size_
char *recv_buffer = (char*)malloc(sizeof(char) * (length * 1000)); // ensuring nothing stupid happens char *recv_buffer = (char*)malloc(sizeof(char) * (length * 1000)); // ensuring nothing stupid happens
if (debug) printf("pre-read\nclient wants %i bytes\n", length); if (debug) printf("pre-read\nclient wants %i bytes\n", length);
bytes = mux_recv(control->iphone, control->connection, recv_buffer, (length * 1000)); bytes = mux_recv(control->connection, recv_buffer, (length * 1000));
if (debug) printf("post-read\nwe got %i bytes\n", bytes); if (debug) printf("post-read\nwe got %i bytes\n", bytes);
if (debug && bytes < 0) { if (debug && bytes < 0) {
printf("lockdownd_securead(): uh oh\n"); printf("lockdownd_securead(): uh oh\n");
...@@ -339,7 +351,7 @@ int lockdownd_start_service(lockdownd_client *control, const char *service) { ...@@ -339,7 +351,7 @@ int lockdownd_start_service(lockdownd_client *control, const char *service) {
key = add_key_str_dict_element(plist, dict, "Service", service, 1); key = add_key_str_dict_element(plist, dict, "Service", service, 1);
if (!key) { xmlFreeDoc(plist); return 0; } if (!key) { xmlFreeDoc(plist); return 0; }
xmlDocDumpMemory(plist, &XML_query, &length); xmlDocDumpMemory(plist, (xmlChar **)&XML_query, &length);
lockdownd_send(control, XML_query, length); lockdownd_send(control, XML_query, length);
free(XML_query); free(XML_query);
......
...@@ -28,9 +28,8 @@ ...@@ -28,9 +28,8 @@
#include <string.h> #include <string.h>
typedef struct { typedef struct {
usbmux_tcp_header *connection; usbmux_connection *connection;
gnutls_session_t *ssl_session; gnutls_session_t *ssl_session;
iPhone *iphone;
int in_SSL; int in_SSL;
char *gtls_buffer_hack; char *gtls_buffer_hack;
int gtls_buffer_hack_len; int gtls_buffer_hack_len;
......
...@@ -29,5 +29,6 @@ xmlNode *add_key_str_dict_element(xmlDocPtr plist, xmlNode *dict, const char *ke ...@@ -29,5 +29,6 @@ xmlNode *add_key_str_dict_element(xmlDocPtr plist, xmlNode *dict, const char *ke
xmlNode *add_child_to_plist(xmlDocPtr plist, const char *name, const char *content, xmlNode *to_node, int depth); xmlNode *add_child_to_plist(xmlDocPtr plist, const char *name, const char *content, xmlNode *to_node, int depth);
void free_plist(xmlDocPtr plist); void free_plist(xmlDocPtr plist);
xmlDocPtr new_plist(); xmlDocPtr new_plist();
char **read_dict_element_strings(xmlNode *dict);
void free_dictionary(char **dictionary); void free_dictionary(char **dictionary);
#endif #endif
...@@ -29,6 +29,9 @@ ...@@ -29,6 +29,9 @@
extern int debug; extern int debug;
static usbmux_connection **connlist = NULL;
static int connections = 0;
usbmux_tcp_header *new_mux_packet(uint16 s_port, uint16 d_port) { usbmux_tcp_header *new_mux_packet(uint16 s_port, uint16 d_port) {
usbmux_tcp_header *conn = (usbmux_tcp_header*)malloc(sizeof(usbmux_tcp_header)); usbmux_tcp_header *conn = (usbmux_tcp_header*)malloc(sizeof(usbmux_tcp_header));
conn->type = htonl(6); conn->type = htonl(6);
...@@ -54,6 +57,47 @@ usbmux_version_header *version_header() { ...@@ -54,6 +57,47 @@ usbmux_version_header *version_header() {
return version; return version;
} }
// Maintenance functions.
/* delete_connection(connection)
* connection: the connection to delete from the tracking list.
* Removes a connection from the list of connections made.
* The list of connections is necessary for buffering.
*/
void delete_connection(usbmux_connection *connection) {
usbmux_connection **newlist = (usbmux_connection**)malloc(sizeof(usbmux_connection*) * (connections - 1));
int i = 0, j = 0;
for (i = 0; i < connections; i++) {
if (connlist[i] == connection) continue;
else {
newlist[j] = connlist[i];
j++;
}
}
free(connlist);
connlist = newlist;
connections--;
if (connection->recv_buffer) free(connection->recv_buffer);
if (connection->header) free(connection->header);
connection->r_len = 0;
free(connection);
}
/* add_connection(connection)
* connection: the connection to add to the global list of connections.
* Adds a connection to the list of connections made.
* The connection list is necessary for buffering.
*/
void add_connection(usbmux_connection *connection) {
usbmux_connection **newlist = (usbmux_connection**)realloc(connlist, sizeof(usbmux_connection*) * (connections+1));
newlist[connections] = connection;
connlist = newlist;
connections++;
}
/* mux_connect(phone, s_port, d_port) /* mux_connect(phone, s_port, d_port)
* This is a higher-level USBMuxTCP-type function. * This is a higher-level USBMuxTCP-type function.
* phone: the iPhone to initialize a connection on. * phone: the iPhone to initialize a connection on.
...@@ -64,27 +108,33 @@ usbmux_version_header *version_header() { ...@@ -64,27 +108,33 @@ usbmux_version_header *version_header() {
* Returns a mux TCP header for the connection which is used for tracking and data transfer. * Returns a mux TCP header for the connection which is used for tracking and data transfer.
*/ */
usbmux_tcp_header *mux_connect(iPhone *phone, uint16 s_port, uint16 d_port) { usbmux_connection *mux_connect(iPhone *phone, uint16 s_port, uint16 d_port) {
if (!phone || !s_port || !d_port) return NULL; if (!phone || !s_port || !d_port) return NULL;
int bytes = 0; int bytes = 0;
// Initialize connection stuff // Initialize connection stuff
usbmux_tcp_header *new_connection; usbmux_connection *new_connection = (usbmux_connection*)malloc(sizeof(usbmux_connection));
new_connection = new_mux_packet(s_port, d_port); new_connection->header = new_mux_packet(s_port, d_port);
usbmux_tcp_header *response; usbmux_tcp_header *response;
response = (usbmux_tcp_header*)malloc(sizeof(usbmux_tcp_header)); response = (usbmux_tcp_header*)malloc(sizeof(usbmux_tcp_header));
// blargg // blargg
if (new_connection) { if (new_connection && new_connection->header) {
new_connection->tcp_flags = 0x02; new_connection->header->tcp_flags = 0x02;
new_connection->length = htonl(new_connection->length); new_connection->header->length = htonl(new_connection->header->length);
new_connection->length16 = htons(new_connection->length16); new_connection->header->length16 = htons(new_connection->header->length16);
if (send_to_phone(phone, (char*)new_connection, sizeof(*new_connection)) >= 0) { if (send_to_phone(phone, (char*)new_connection->header, sizeof(usbmux_tcp_header)) >= 0) {
bytes = recv_from_phone(phone, (char*)response, sizeof(*response)); bytes = recv_from_phone(phone, (char*)response, sizeof(*response));
if (response->tcp_flags != 0x12) return NULL; if (response->tcp_flags != 0x12) return NULL;
else { else {
new_connection->tcp_flags = 0x10; if (debug) printf("mux_connect: connection success\n");
new_connection->scnt = 1; new_connection->header->tcp_flags = 0x10;
new_connection->ocnt = 1; new_connection->header->scnt = 1;
new_connection->header->ocnt = 1;
add_connection(new_connection);
new_connection->phone = phone;
new_connection->recv_buffer = NULL;
new_connection->r_len = 0;
add_connection(new_connection);
return new_connection; return new_connection;
} }
} else { } else {
...@@ -103,23 +153,24 @@ usbmux_tcp_header *mux_connect(iPhone *phone, uint16 s_port, uint16 d_port) { ...@@ -103,23 +153,24 @@ usbmux_tcp_header *mux_connect(iPhone *phone, uint16 s_port, uint16 d_port) {
* *
* Doesn't return anything; WILL FREE THE CONNECTION'S MEMORY!!! * Doesn't return anything; WILL FREE THE CONNECTION'S MEMORY!!!
*/ */
void mux_close_connection(iPhone *phone, usbmux_tcp_header *connection) {
if (!phone || !connection) return;
connection->tcp_flags = 0x04; void mux_close_connection(usbmux_connection *connection) {
connection->scnt = htonl(connection->scnt); if (!connection || !connection->phone) return;
connection->ocnt = htonl(connection->ocnt);
connection->header->tcp_flags = 0x04;
connection->header->scnt = htonl(connection->header->scnt);
connection->header->ocnt = htonl(connection->header->ocnt);
int bytes = 0; int bytes = 0;
bytes = usb_bulk_write(phone->device, BULKOUT, (char*)connection, sizeof(*connection), 800); bytes = usb_bulk_write(connection->phone->device, BULKOUT, (char*)connection->header, sizeof(usbmux_tcp_header), 800);
if(debug && bytes < 0) if(debug && bytes < 0)
printf("mux_close_connection(): when writing, libusb gave me the error: %s\n", usb_strerror()); printf("mux_close_connection(): when writing, libusb gave me the error: %s\n", usb_strerror());
bytes = usb_bulk_read(phone->device, BULKIN, (char*)connection, sizeof(*connection), 800); bytes = usb_bulk_read(connection->phone->device, BULKIN, (char*)connection->header, sizeof(usbmux_tcp_header), 800);
if(debug && bytes < 0) if(debug && bytes < 0)
printf("get_iPhone(): when reading, libusb gave me the error: %s\n", usb_strerror()); printf("get_iPhone(): when reading, libusb gave me the error: %s\n", usb_strerror());
free(connection); delete_connection(connection);
} }
/* mux_send(phone, connection, data, datalen) /* mux_send(phone, connection, data, datalen)
...@@ -131,40 +182,46 @@ void mux_close_connection(iPhone *phone, usbmux_tcp_header *connection) { ...@@ -131,40 +182,46 @@ void mux_close_connection(iPhone *phone, usbmux_tcp_header *connection) {
* *
* Returns number of bytes sent, minus the header (28), or -1 on error. * Returns number of bytes sent, minus the header (28), or -1 on error.
*/ */
int mux_send(iPhone *phone, usbmux_tcp_header *connection, char *data, uint32 datalen) { int mux_send(usbmux_connection *connection, const char *data, uint32 datalen) {
if (!phone || !connection || !data || datalen == 0) return -1; if (!connection->phone || !connection || !data || datalen == 0) return -1;
// connection->scnt and connection->ocnt should already be in host notation... // connection->scnt and connection->ocnt should already be in host notation...
// we don't need to change them juuuust yet. // we don't need to change them juuuust yet.
int bytes = 0; int bytes = 0;
if (debug) printf("mux_send(): client wants to send %i bytes\n", datalen); if (debug) printf("mux_send(): client wants to send %i bytes\n", datalen);
char *buffer = (char*)malloc(sizeof(*connection) + datalen + 2); // allow 2 bytes of safety padding char *buffer = (char*)malloc(sizeof(usbmux_tcp_header) + datalen + 2); // allow 2 bytes of safety padding
// Set the length and pre-emptively htonl/htons it // Set the length and pre-emptively htonl/htons it
connection->length = htonl(sizeof(*connection) + datalen); connection->header->length = htonl(sizeof(usbmux_tcp_header) + datalen);
connection->length16 = htons(sizeof(*connection) + datalen); connection->header->length16 = htons(sizeof(usbmux_tcp_header) + datalen);
// Put scnt and ocnt into big-endian notation // Put scnt and ocnt into big-endian notation
connection->scnt = htonl(connection->scnt); connection->header->scnt = htonl(connection->header->scnt);
connection->ocnt = htonl(connection->ocnt); connection->header->ocnt = htonl(connection->header->ocnt);
// Concatenation of stuff in the buffer. // Concatenation of stuff in the buffer.
memcpy(buffer, connection, sizeof(*connection)); memcpy(buffer, connection->header, sizeof(usbmux_tcp_header));
memcpy(buffer+sizeof(*connection)/*+sizeof(datalen)*/, data, datalen); memcpy(buffer+sizeof(usbmux_tcp_header), data, datalen);
// We have a buffer full of data, we should now send it to the phone. // We have a buffer full of data, we should now send it to the phone.
if (debug) printf("actually sending %i bytes of data at %x\n", sizeof(*connection)+datalen, buffer); if (debug) printf("actually sending %i bytes of data at %x\n", sizeof(usbmux_tcp_header)+datalen, buffer);
bytes = send_to_phone(phone, buffer, sizeof(*connection)+datalen);
bytes = send_to_phone(connection->phone, buffer, sizeof(usbmux_tcp_header)+datalen);
if (debug) printf("mux_send: sent %i bytes!\n", bytes);
// Now that we've sent it off, we can clean up after our sloppy selves. // Now that we've sent it off, we can clean up after our sloppy selves.
free(buffer); if (debug) {
FILE *packet = fopen("packet", "a+");
fwrite(buffer, 1, bytes, packet);
fclose(packet);
printf("\n");
}
if (buffer) free(buffer);
// Re-calculate scnt and ocnt // Re-calculate scnt and ocnt
connection->scnt = ntohl(connection->scnt) + datalen; connection->header->scnt = ntohl(connection->header->scnt) + datalen;
connection->ocnt = ntohl(connection->ocnt); connection->header->ocnt = ntohl(connection->header->ocnt);
// Revert lengths // Revert lengths
connection->length = ntohl(connection->length); connection->header->length = ntohl(connection->header->length);
connection->length16 = ntohs(connection->length16); connection->header->length16 = ntohs(connection->header->length16);
// Now return the bytes. // Now return the bytes.
if (bytes < sizeof(*connection)+datalen) { if (bytes < sizeof(*connection)+datalen) {
...@@ -186,39 +243,103 @@ int mux_send(iPhone *phone, usbmux_tcp_header *connection, char *data, uint32 da ...@@ -186,39 +243,103 @@ int mux_send(iPhone *phone, usbmux_tcp_header *connection, char *data, uint32 da
* Returns: how many bytes were read, or -1 if something bad happens. * Returns: how many bytes were read, or -1 if something bad happens.
*/ */
int mux_recv(iPhone *phone, usbmux_tcp_header *connection, char *data, uint32 datalen) { int mux_recv(usbmux_connection *connection, char *data, uint32 datalen) {
char *buffer = (char*)malloc(sizeof(*connection) + sizeof(datalen) + datalen); /*
int bytes = 0, my_datalen = 0; * Order of operation:
* 1.) Check if the connection has a pre-received buffer.
* 2.) If so, fill data with the buffer, as much as needed.
* a.) Return quickly if the buffer has enough
* b.) If the buffer is only part of the datalen, get the rest of datalen (and if we can't, just return)
* 3.) If not, receive directly from the phone.
* a.) Check incoming packet's ports. If proper, follow proper buffering and receiving operation.
* b.) If not, find the connection the ports belong to and fill that connection's buffer, then return mux_recv with the same args to try again.
*/
if (debug) printf("mux_recv: datalen == %i\n", datalen); if (debug) printf("mux_recv: datalen == %i\n", datalen);
bytes = recv_from_phone(phone, buffer, sizeof(*connection) + datalen); int bytes = 0, i = 0, complex = 0, offset = 0;
if (debug) printf("mux_recv: bytes == %i\n", bytes); char *buffer = NULL;
if (bytes < datalen) { usbmux_tcp_header *header = NULL;
if (connection->recv_buffer) {
if (connection->r_len >= datalen) {
memcpy(data, connection->recv_buffer, datalen);
if (connection->r_len == datalen) {
// reset everything
free(connection->recv_buffer);
connection->r_len = 0;
connection->recv_buffer = NULL;
} else {
buffer = (char*)malloc(sizeof(char) * (connection->r_len - datalen));
memcpy(buffer, connection->recv_buffer+datalen, (connection->r_len - datalen));
connection->r_len -= datalen;
free(connection->recv_buffer);
connection->recv_buffer = buffer;
}
// Since we were able to fill the data straight from our buffer, we can just return datalen. See 2a above.
return datalen;
} else {
memcpy(data, connection->recv_buffer, connection->r_len);
free(connection->recv_buffer); // don't need to deal with anymore, but...
offset = connection->r_len; // see #2b, above
connection->r_len = 0;
}
} // End of what to do if we have a pre-buffer. See #1 and #2 above.
buffer = (char*)malloc(sizeof(char) * 131072); // make sure we get enough ;)
// See #3.
bytes = recv_from_phone(connection->phone, buffer, 131072);
if (bytes < 28) { if (bytes < 28) {
// if they didn't do that annoying thing, something else mighta happened.
if (debug) printf("mux_recv: bytes too low anyway!\n");
free(buffer); free(buffer);
if (debug) printf("mux_recv: Did not even get the header.\n");
return -1; return -1;
} else if (bytes == 28) { // no data... }
free(buffer);
return 0; header = (usbmux_tcp_header*)buffer;
} else { // bytes > 28 if (header->sport != connection->header->dport || header->dport != connection->header->sport) {
my_datalen = ntohl(buffer[4]) - 28; // Ooooops -- we got someone else's packet.
connection->ocnt += my_datalen; // We gotta stick it in their buffer. (Take that any old way you want ;) )
memcpy(data, buffer+28, bytes - 28); for (i = 0; i < connections; i++) {
if (connlist[i]->header->sport == header->dport && connlist[i]->header->dport == header->sport) {
// we have a winner.
connlist[i]->r_len += bytes - 28;
connlist[i]->recv_buffer = (char*)realloc(connlist[i]->recv_buffer, sizeof(char) * connection->r_len); // grow their buffer
complex = connlist[i]->r_len - (bytes - 28);
memcpy(connlist[i]->recv_buffer+complex, buffer+28, bytes-28); // paste into their buffer
connlist[i]->header->ocnt += bytes-28;
}
}
// If it wasn't ours, it's been handled by this point... or forgotten.
// Free our buffer and continue.
free(buffer); free(buffer);
if (debug) printf("mux_recv: bytes received: %i\n", bytes - 28); buffer = NULL;
return bytes - 28; return mux_recv(connection, data, datalen); // recurse back in to try again
} }
} else {// all's good, they didn't do anything bonky.
my_datalen = ntohl(buffer[4]) - 28; // The packet was absolutely meant for us if it hits this point.
connection->ocnt += my_datalen; // The pre-buffer has been taken care of, so, again, if we're at this point we have to read from the phone.
if (bytes == (datalen+28)) memcpy(data, buffer+28, datalen);
else if (bytes == datalen) memcpy(data, buffer+28, datalen-28); if ((bytes-28) > datalen) {
// Copy what we need into the data, buffer the rest because we can.
memcpy(data+offset, buffer+28, datalen); // data+offset: see #2b, above
complex = connection->r_len + (bytes-28) - datalen;
connection->recv_buffer = (char*)realloc(connection->recv_buffer, (sizeof(char) * complex));
connection->r_len = complex;
complex = connection->r_len - (bytes-28) - datalen;
memcpy(connection->recv_buffer+complex, buffer+28+datalen, (bytes-28) - datalen);
free(buffer);
connection->header->ocnt += bytes-28;
return datalen;
} else {
// Fill the data with what we have, and just return.
memcpy(data+offset, buffer+28, bytes-28); // data+offset: see #2b, above
connection->header->ocnt += bytes-28;
free(buffer); free(buffer);
if (debug) printf("mux_recv: bytes received: %i\n", bytes - 28); return (bytes-28);
return bytes - 28;
} }
return bytes; // If we get to this point, 'tis probably bad.
if (debug) printf("mux_recv: Heisenbug: bytes and datalen not matching up\n");
return -1;
} }
...@@ -43,6 +43,13 @@ typedef struct { ...@@ -43,6 +43,13 @@ typedef struct {
uint16 window, nullnull, length16; uint16 window, nullnull, length16;
} usbmux_tcp_header; } usbmux_tcp_header;
typedef struct {
usbmux_tcp_header *header;
iPhone *phone;
char *recv_buffer;
int r_len;
} usbmux_connection;
usbmux_tcp_header *new_mux_packet(uint16 s_port, uint16 d_port); usbmux_tcp_header *new_mux_packet(uint16 s_port, uint16 d_port);
typedef struct { typedef struct {
...@@ -51,8 +58,10 @@ typedef struct { ...@@ -51,8 +58,10 @@ typedef struct {
usbmux_version_header *version_header(); usbmux_version_header *version_header();
usbmux_tcp_header *mux_connect(iPhone *phone, uint16 s_port, uint16 d_port); usbmux_connection *mux_connect(iPhone *phone, uint16 s_port, uint16 d_port);
void mux_close_connection(iPhone *phone, usbmux_tcp_header *connection); void mux_close_connection(usbmux_connection *connection);
int mux_send(iPhone *phone, usbmux_tcp_header *connection, char *data, uint32 datalen); int mux_send(usbmux_connection *connection, const char *data, uint32 datalen);
int mux_recv(iPhone *phone, usbmux_tcp_header *connection, char *data, uint32 datalen); int mux_recv(usbmux_connection *connection, char *data, uint32 datalen);
#endif #endif
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
*/ */
#include <glib.h> #include <glib.h>
#include <stdio.h>
#include <string.h>
#include "userpref.h" #include "userpref.h"
#define LIBIPHONE_CONF_DIR "libiphone" #define LIBIPHONE_CONF_DIR "libiphone"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment