diff options
| -rw-r--r-- | AFC.c | 162 | ||||
| -rw-r--r-- | AFC.h | 8 | ||||
| -rw-r--r-- | lockdown.c | 22 | ||||
| -rw-r--r-- | main.c | 25 | 
4 files changed, 180 insertions, 37 deletions
| @@ -17,7 +17,7 @@ AFClient *afc_connect(iPhone *phone, int s_port, int d_port) {  		if (client->afc_packet) {  			client->phone = phone;  			client->afc_packet->packet_num = 0; -			client->afc_packet->unknown1 = client->afc_packet->unknown2 = client->afc_packet->unknown3 = client->afc_packet->unknown4 = 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->header2 = 0x4141504C;  			client->file_handle = 0; @@ -50,29 +50,55 @@ int count_nullspaces(char *string, int number) {  int dispatch_AFC_packet(AFClient *client, char *data, int length) {  	char *buffer; -	int bytes = 0; +	int bytes = 0, offset = 0;  	if (!client || !client->connection || !client->phone || !client->afc_packet) return 0;  	if (!data || !length) length = 0;  	client->afc_packet->packet_num++; -	client->afc_packet->entire_length = client->afc_packet->this_length = (length) ? sizeof(AFCPacket) + length + 1 : sizeof(AFCPacket); -	 -	if (!length) { -		bytes = mux_send(client->phone, client->connection, (char*)client->afc_packet, client->afc_packet->this_length); -		if (bytes <= 0) return 0; -		else return bytes; -	} else { -		buffer = (char*)malloc(sizeof(char) * client->afc_packet->this_length); -		memcpy(buffer, client->afc_packet, sizeof(AFCPacket)); -		memcpy(buffer+sizeof(AFCPacket), data, length); -		buffer[client->afc_packet->this_length-1] = '\0'; +	if (!client->afc_packet->entire_length) client->afc_packet->entire_length = client->afc_packet->this_length = (length) ? sizeof(AFCPacket) + length + 1 : sizeof(AFCPacket); +	if (!client->afc_packet->this_length) client->afc_packet->this_length = sizeof(AFCPacket); +		 +	if (client->afc_packet->this_length != client->afc_packet->entire_length) { +		// We want to send two segments; buffer+sizeof(AFCPacket) to this_length is the parameters +		// And everything beyond that is the next packet. (for writing) +		char *buffer = (char*)malloc(client->afc_packet->this_length); +		memcpy(buffer, (char*)client->afc_packet, sizeof(AFCPacket)); +		offset = client->afc_packet->this_length - sizeof(AFCPacket); +		if (debug) printf("dispatch_AFC_packet: Offset: %i\n", offset); +		if ((length) < (client->afc_packet->entire_length - client->afc_packet->this_length)) { +			if (debug) printf("dispatch_AFC_packet: Length did not resemble what it was supposed to based on the packet.\nlength minus offset: %i\nrest of packet: %i\n", length-offset, client->afc_packet->entire_length - client->afc_packet->this_length); +			free(buffer); +			return 0; +		} +		if (debug) printf("dispatch_AFC_packet: fucked-up packet method (probably a write)\n"); +		memcpy(buffer+sizeof(AFCPacket), data, offset); +		bytes = mux_send(client->phone, client->connection, buffer, client->afc_packet->this_length); +		free(buffer); +		if (bytes <= 0) { return 0; } +		if (debug) { +			printf("dispatch_AFC_packet: sent the first now go with the second\n"); +			printf("Length: %i\n", length-offset); +			printf("Buffer: \n"); +			fwrite(data+offset, 1, length-offset, stdout); +		} +		 +		bytes = mux_send(client->phone, client->connection, data+offset, length-offset); +		if (bytes <= 0) { return 0; } +		else { return bytes; } +	} else { +		if (debug) printf("dispatch_AFC_packet doin things the old way\n"); +		char *buffer = (char*)malloc(sizeof(char) * client->afc_packet->this_length); +		if (debug) printf("dispatch_AFC_packet packet length = %i\n", client->afc_packet->this_length); +		memcpy(buffer, (char*)client->afc_packet, sizeof(AFCPacket)); +		if (debug) printf("dispatch_AFC_packet packet data follows\n"); +		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) printf("\n");  		bytes = mux_send(client->phone, client->connection, buffer, client->afc_packet->this_length); -		free(buffer); // don't need it  		if (bytes <= 0) return 0;  		else return bytes;  	} -	  	return 0;  } @@ -103,19 +129,23 @@ int receive_AFC_data(AFClient *client, char **dump_here) {  	uint32 param1 = buffer[sizeof(AFCPacket)];  	free(buffer); -	if (r_packet->operation == 0x01) { -		printf("Oops? Bad operation code received.\n"); -		if (param1 == 0) printf("... false alarm, but still\n"); -		else printf("Errno %i\n", param1); +	if (r_packet->operation == 0x01 && !((client->afc_packet->operation == AFC_DELETE && param1 == 7))) { +		if (debug) printf("Oops? Bad operation code received.\n"); +		if (param1 == 0) { +			if (debug) printf("... false alarm, but still\n"); +			return 1; +		} +		else { if (debug) printf("Errno %i\n", param1); }  		free(r_packet);  		*dump_here = NULL;  		return 0;  	} else { -		printf("Operation code %x\nFull length %i and this length %i\n", r_packet->operation, r_packet->entire_length, r_packet->this_length); +		if (debug) printf("Operation code %x\nFull length %i and this length %i\n", r_packet->operation, r_packet->entire_length, r_packet->this_length);  	}  	recv_len = r_packet->entire_length - r_packet->this_length;  	free(r_packet); +	if (!recv_len) return bytes;  	buffer = (char*)malloc(sizeof(char) * recv_len);  	bytes = mux_recv(client->phone, client->connection, buffer, recv_len);  	if (bytes <= 0) { @@ -133,6 +163,7 @@ char **afc_get_dir_list(AFClient *client, char *dir) {  	client->afc_packet->operation = AFC_LIST_DIR;  	int bytes = 0;  	char *blah = NULL, **list = NULL; +	client->afc_packet->entire_length = client->afc_packet->this_length = 0;  	bytes = dispatch_AFC_packet(client, dir, strlen(dir));  	if (!bytes) return NULL; @@ -159,8 +190,49 @@ char **make_strings_list(char *tokens, int true_length) {  	return list;  } +int afc_delete_file(AFClient *client, const char *path) { +	if (!client || !path || !client->afc_packet || !client->phone ||!client->connection) return 0; + +	char *receive = NULL; +	client->afc_packet->this_length = client->afc_packet->entire_length = 0; +	client->afc_packet->operation = AFC_DELETE; +	int bytes; +	bytes = dispatch_AFC_packet(client, path, strlen(path)); +	if (bytes <= 0) return 0; +	 +	bytes = receive_AFC_data(client, &receive); +	free(receive); +	if (bytes <= 0) return 0; +	else return 1; +} + +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; +	 +	char *receive = NULL; +	char *send = (char*)malloc(sizeof(char) * (strlen(from) + strlen(to) + 1 + sizeof(uint32))); +	int bytes = 0; +	 +	memcpy(send, from, strlen(from)+1); +	memcpy(send+strlen(from)+1, to, strlen(to)); +	fwrite(send, 1, strlen(from)+1+strlen(to), stdout); +	printf("\n"); +	client->afc_packet->entire_length = client->afc_packet->this_length = 0; +	client->afc_packet->operation = AFC_RENAME; +	bytes = dispatch_AFC_packet(client, send, strlen(to) + strlen(from) + 2); +	if (bytes <= 0) return 0; +	 +	bytes = receive_AFC_data(client, &receive); +	free(receive); +	if (bytes <= 0) return 0; +	else return 1; +} + +	 +	  AFCFile *afc_get_file_info(AFClient *client, char *path) {  	client->afc_packet->operation = AFC_GET_INFO; +	client->afc_packet->entire_length = client->afc_packet->this_length = 0;  	dispatch_AFC_packet(client, path, strlen(path));  	char *received, **list; @@ -210,26 +282,24 @@ AFCFile *afc_open_file(AFClient *client, const char *filename, uint32 file_mode)  	int bytes = 0, length_thing = 0;  	client->afc_packet->operation = AFC_FILE_OPEN; +	client->afc_packet->entire_length = client->afc_packet->this_length = 0;  	bytes = dispatch_AFC_packet(client, further_data, 8+strlen(filename));  	free(further_data);  	if (bytes <= 0) { -		printf("didn't read enough\n"); +		if (debug) printf("didn't read enough\n");  		return NULL;  	} else { -		printf("O HAI\n");  		length_thing = receive_AFC_data(client, &further_data);  		if (length_thing && further_data) { -			printf("ARA\n");  			file_infos = afc_get_file_info(client, filename);  			memcpy(&file_infos->filehandle, further_data, 4); -			printf("gr\n");  			return file_infos;  		} else { -			printf("didn't get further data or something\n"); +			if (debug) printf("didn't get further data or something\n");  			return NULL;  		}  	} -	printf("what the fuck\n"); +	if (debug) printf("what the fuck\n");  	return NULL;  } @@ -243,14 +313,17 @@ int afc_read_file(AFClient *client, AFCFile *file, char *data, int length) {  	int bytes = 0;  	client->afc_packet->operation = AFC_READ; -	bytes = dispatch_AFC_packet(client, packet, sizeof(AFCFilePacket)); +	client->afc_packet->entire_length = client->afc_packet->this_length = 0; +	bytes = dispatch_AFC_packet(client, (char*)packet, sizeof(AFCFilePacket));  	if (bytes > 0) {  		bytes = receive_AFC_data(client, &input);  		if (bytes <= 0) { +			if (input) free(input);  			return -1;  		} else {  			memcpy(data, input, (bytes > length) ? length : bytes); +			free(input);  			return (bytes > length) ? length : bytes;  		}  	} else { @@ -259,21 +332,50 @@ int afc_read_file(AFClient *client, AFCFile *file, char *data, int length) {  	return 0;  } +int afc_write_file(AFClient *client, AFCFile *file, char *data, int length) { +	char *acknowledgement = NULL; +	if (!client ||!client->afc_packet ||!client->phone || !client->connection || !file) return -1; +	client->afc_packet->this_length = sizeof(AFCPacket) + 8; +	client->afc_packet->entire_length = client->afc_packet->this_length + length; +	client->afc_packet->operation = AFC_WRITE; +	if (debug) printf("afc_write_file: Write length: %i\n", length); +	uint32 zero = 0, bytes = 0; +	 +	char *out_buffer = NULL; +	out_buffer = (char*)malloc(sizeof(char) * client->afc_packet->entire_length - sizeof(AFCPacket)); +	memcpy(out_buffer, (char*)&file->filehandle, sizeof(uint32)); +	memcpy(out_buffer+4, (char*)&zero, sizeof(uint32)); +	memcpy(out_buffer+8, data, length); +	 +	bytes = dispatch_AFC_packet(client, out_buffer, length + 8); +	if (!bytes) return -1; +	 +	zero = bytes; +	bytes = receive_AFC_data(client, &acknowledgement); +	if (bytes <= 0) { +		if (debug) printf("afc_write_file: uh oh?\n"); +	} +	 +	return zero; +} +  void afc_close_file(AFClient *client, AFCFile *file) {  	char *buffer = malloc(sizeof(char) * 8);  	uint32 zero = 0;  	if (debug) printf("File handle %i\n", file->filehandle);  	memcpy(buffer, &file->filehandle, sizeof(uint32)); -	memcpy(buffer, &zero, sizeof(zero)); +	memcpy(buffer+sizeof(uint32), &zero, sizeof(zero));  	client->afc_packet->operation = AFC_FILE_CLOSE;  	int bytes = 0; +	client->afc_packet->entire_length = client->afc_packet->this_length = 0;  	bytes = dispatch_AFC_packet(client, buffer, sizeof(char) * 8); +  	free(buffer); +	client->afc_packet->entire_length = client->afc_packet->this_length = 0;  	if (!bytes) return;  	bytes = receive_AFC_data(client, &buffer); -	if (bytes<=0 && !buffer) printf("closefile: all went as expected\n"); -	else { printf("We have a buffer!??!?\nLength %i\n", bytes); fwrite(buffer, 1, bytes, stdout); printf("\n"); } +	return;  	if (buffer) free(buffer); // we're *SUPPOSED* to get an "error" here.   } @@ -53,11 +53,14 @@ enum {  	AFC_GET_INFO = 0x0000000a,  	AFC_GET_DEVINFO = 0x0000000b,  	AFC_LIST_DIR = 0x00000003, +	AFC_DELETE = 0x00000008, +	AFC_RENAME = 0x00000018,  	AFC_SUCCESS_RESPONSE = 0x00000002,  	AFC_FILE_OPEN = 0x0000000d,  	AFC_FILE_CLOSE = 0x00000014,  	AFC_FILE_HANDLE = 0x0000000e, -	AFC_READ = 0x0000000f +	AFC_READ = 0x0000000f, +	AFC_WRITE = 0x00000010  };  AFClient *afc_connect(iPhone *phone, int s_port, int d_port); @@ -72,3 +75,6 @@ AFCFile *afc_get_file_info(AFClient *client, char *path);  AFCFile *afc_open_file(AFClient *client, const char *filename, uint32 file_mode);  void afc_close_file(AFClient *client, AFCFile *file);  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_delete_file(AFClient *client, const char *path); +int afc_rename_file(AFClient *client, const char *from, const char *to); @@ -149,15 +149,16 @@ int lockdownd_start_SSL_session(lockdownd_client *control, const char *HostID) {  		for (i = 0; strcmp(dictionary[i], ""); i+=2) {  			if (!strcmp(dictionary[i], "Result") && !strcmp(dictionary[i+1], "Success")) {  				// Set up GnuTLS... +				//gnutls_anon_client_credentials_t anoncred;  				gnutls_certificate_credentials_t xcred; -				  				if (debug) printf("We started the session OK, now trying GnuTLS\n");  				errno = 0;  				gnutls_global_init(); +				//gnutls_anon_allocate_client_credentials(&anoncred);  				gnutls_certificate_allocate_credentials(&xcred);  				gnutls_certificate_set_x509_trust_file(xcred, "hostcert.pem", GNUTLS_X509_FMT_PEM);  				gnutls_init(control->ssl_session, GNUTLS_CLIENT); -				if ((return_me = gnutls_priority_set_direct(*control->ssl_session, "NORMAL:+VERS-SSL3.0", NULL)) < 0) { +				if ((return_me = gnutls_priority_set_direct(*control->ssl_session, "NONE:+VERS-SSL3.0:+ANON-DH:+RSA:+AES-128-CBC:+AES-256-CBC:+SHA1:+SHA256:+SHA512:+MD5:+COMP-NULL", NULL)) < 0) {  					printf("oops? bad options?\n");  					gnutls_perror(return_me);  					return 0; @@ -214,6 +215,14 @@ ssize_t lockdownd_secuwrite(gnutls_transport_ptr_t transport, char *buffer, size  	if (debug) printf("pre-send\nlength = %i\n", length);  	bytes = mux_send(control->iphone, control->connection, buffer, length);  	if (debug) printf("post-send\nsent %i bytes\n", bytes); +	if (debug) { +		FILE *my_ssl_packet = fopen("sslpacketwrite.out", "w+"); +		fwrite(buffer, 1, length, my_ssl_packet); +		fflush(my_ssl_packet); +		printf("Wrote SSL packet to drive, too.\n"); +		fclose(my_ssl_packet); +	} +	  	return bytes;  } @@ -251,11 +260,16 @@ ssize_t lockdownd_securead(gnutls_transport_ptr_t transport, char *buffer, size_  		}  	}  	// End buffering hack! -	char *recv_buffer = (char*)malloc(sizeof(char) * (length * 400)); // 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); -	bytes = mux_recv(control->iphone, control->connection, recv_buffer, (length * 400)); +	bytes = mux_recv(control->iphone, control->connection, recv_buffer, (length * 1000));  	if (debug) printf("post-read\nwe got %i bytes\n", bytes); +	if (debug && bytes < 0) { +		printf("lockdownd_securead(): uh oh\n"); +		printf("I believe what we have here is a failure to communicate... libusb says %s but strerror says %s\n", usb_strerror(), strerror(errno)); +		return bytes + 28; // an errno +	}  	if (bytes >= length) {  		if (bytes > length) {  			if (debug) printf("lockdownd_securead: Client deliberately read less data than was there; resorting to GnuTLS buffering hack.\n"); @@ -36,12 +36,13 @@ int main(int argc, char *argv[]) {  	}  	printf("Now starting SSL.\n"); -	if (!lockdownd_start_SSL_session(control, "29942970-207913891623273984")) { +//	if (!lockdownd_start_SSL_session(control, "29942970-207913891623273984")) { +	if (!lockdownd_start_SSL_session(control, "2994593482385678618538736")) {  		printf("Error happened in GnuTLS...\n");  	} else {   		printf("... we're in SSL with the phone... !?\n"); +		port = lockdownd_start_service(control, "com.apple.afc");  	} -	port = lockdownd_start_service(control, "com.apple.afc");  	if (port) {  		printf("Start Service successful -- connect on port %i\n", port);  		AFClient *afc = afc_connect(phone, 3432, port); @@ -69,6 +70,26 @@ int main(int argc, char *argv[]) {  				free(my_file);  				free(file_data);  			} else printf("couldn't open a file\n"); +			 +			my_file = afc_open_file(afc, "/readme.libiphone.fx", AFC_FILE_WRITE); +			if (my_file) { +				char *outdatafile = strdup("this is a bitchin text file\n"); +				bytes = afc_write_file(afc, my_file, outdatafile, strlen(outdatafile)); +				free(outdatafile); +				if (bytes > 0) printf("Wrote a surprise. ;)\n"); +				else printf("I wanted to write a surprise, but... :(\n"); +				afc_close_file(afc, my_file); +				free(my_file); +			} +			printf("Deleting a file...\n"); +			bytes = afc_delete_file(afc, "/delme"); +			if (bytes) printf("Success.\n"); +			else printf("Failure.\n"); +			 +			printf("Renaming a file...\n"); +			bytes = afc_rename_file(afc, "/renme", "/renme2"); +			if (bytes > 0) printf("Success.\n"); +			else printf("Failure.\n");  		}  		afc_disconnect(afc);  	} else { | 
