summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dev/Makefile.am9
-rw-r--r--dev/plutil.c171
-rw-r--r--dev/plutil.h13
-rw-r--r--src/AFC.c46
-rw-r--r--src/AFC.h10
-rw-r--r--src/lockdown.c14
-rw-r--r--src/plist.c284
-rw-r--r--src/plist.h38
-rw-r--r--src/usbmux.c2
-rw-r--r--src/usbmux.h20
10 files changed, 557 insertions, 50 deletions
diff --git a/dev/Makefile.am b/dev/Makefile.am
index 4833728..95b4d61 100644
--- a/dev/Makefile.am
+++ b/dev/Makefile.am
@@ -3,7 +3,7 @@ INCLUDES = -I$(top_srcdir)/include
AM_CFLAGS = $(libxml2_CFLAGS) $(libusb_CFLAGS) $(libglib2_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(libgthread2_CFLAGS) -g
AM_LDFLAGS = $(libxml2_LIBS) $(libusb_LIBS) $(libglib2_LIBS) $(libgnutls_LIBS) $(libtasn1_LIBS) $(libgthread2_LIBS)
-bin_PROGRAMS = iphoneclient lckd-client afccheck
+bin_PROGRAMS = iphoneclient lckd-client afccheck plutil
iphoneclient_SOURCES = main.c
iphoneclient_LDADD = ../src/libiphone.la
@@ -16,4 +16,9 @@ lckd_client_LDADD = ../src/libiphone.la
afccheck_SOURCES = afccheck.c
afccheck_CFLAGS = $(AM_CFLAGS)
afccheck_LDFLAGS = $(AM_LDFLAGS)
-afccheck_LDADD = ../src/libiphone.la \ No newline at end of file
+afccheck_LDADD = ../src/libiphone.la
+
+plutil_SOURCES = plutil.c
+plutil_CFLAGS = $(AM_CFLAGS)
+plutil_LDFLAGS = $(AM_LDFLAGS)
+plutil_LDADD = ../src/libiphone.la
diff --git a/dev/plutil.c b/dev/plutil.c
new file mode 100644
index 0000000..208d7df
--- /dev/null
+++ b/dev/plutil.c
@@ -0,0 +1,171 @@
+/*
+ * main.c for plistutil
+ * right now just prints debug shit
+ */
+
+#include "../src/plist.h"
+#include "plutil.h"
+
+int debug = 0;
+
+void print_nodes(bplist_node *root_node) {
+ // Yay, great. Let's print the list of nodes recursively...
+ int i = 0;
+ if (!root_node) return; // or not, because the programmer's stupid.
+
+ switch (root_node->type) {
+ case BPLIST_DICT:
+ printf("Dictionary node.\nLength %i\n", root_node->length);
+ for (i = 0; i < (root_node->length * 2); i+=2) {
+ // HI!
+ printf("Key: ");
+ print_nodes(root_node->subnodes[i]);
+ printf("Value: ");
+ print_nodes(root_node->subnodes[i+1]);
+ }
+ printf("End dictionary node.\n\n");
+ break;
+
+ case BPLIST_ARRAY:
+ printf("Array node.\n");
+ for (i = 0; i < root_node->length; i++) {
+ printf("\tElement %i: ", i);
+ print_nodes(root_node->subnodes[i]);
+ }
+ break;
+
+ case BPLIST_INT:
+ if (root_node->length == sizeof(uint8_t)) {
+ printf("Integer: %i\n", root_node->intval8);
+ } else if (root_node->length == sizeof(uint16_t)) {
+ printf("Integer: %i\n", root_node->intval16);
+ } else if (root_node->length == sizeof(uint32_t)) {
+ printf("Integer: %i\n", root_node->intval32);
+ }
+ break;
+
+ case BPLIST_STRING:
+ case BPLIST_DATA:
+ printf("String/data: ");
+ fwrite(root_node->strval, sizeof(char), root_node->length, stdout);
+ fflush(stdout);
+ printf("\n");
+ break;
+
+ case BPLIST_UNICODE:
+ printf("Unicode data, may appear crappy: ");
+ fwrite(root_node->unicodeval, sizeof(wchar_t), root_node->length, stdout);
+ fflush(stdout);
+ printf("\n");
+ break;
+
+ case BPLIST_TRUE:
+ printf("True.\n");
+ break;
+
+ case BPLIST_FALSE:
+ printf("False.\n");
+ break;
+
+ case BPLIST_REAL:
+ case BPLIST_DATE:
+ printf("Real(?): %f\n", root_node->realval);
+ break;
+
+ default:
+ printf("oops\nType set to %x and length is %i\n", root_node->type, root_node->length);
+ break;
+ }
+}
+
+int main(int argc, char *argv[]) {
+ struct stat *filestats = (struct stat *)malloc(sizeof(struct stat));
+ uint32_t position = 0;
+ Options *options = parse_arguments(argc, argv);
+ int argh = 0;
+
+ printf("plistutil version 0.2 written by FxChiP\n");
+
+ if (!options) {
+ print_usage();
+ return 0;
+ }
+
+ debug = options->debug;
+
+ FILE *bplist = fopen(options->in_file, "r");
+
+ stat(options->in_file, filestats);
+
+ printf("here?\n");
+ char *bplist_entire = (char*)malloc(sizeof(char) * (filestats->st_size + 1));
+ //argh = fgets(bplist_entire, filestats->st_size, bplist);
+ argh = fread(bplist_entire, sizeof(char), filestats->st_size, bplist);
+ printf("read %i bytes\n", argh);
+ fclose(bplist);
+ printf("or here?\n");
+ // bplist_entire contains our stuff
+ bplist_node *root_node;
+ root_node = parse_nodes(bplist_entire, filestats->st_size, &position);
+ printf("plutil debug mode\n\n");
+ printf("file size %i\n\n", filestats->st_size);
+ if (!root_node) {
+ printf("Invalid binary plist (or some other error occurred.)\n");
+ return 0;
+ }
+ print_nodes(root_node);
+ return 0;
+ }
+
+Options *parse_arguments(int argc, char *argv[]) {
+ int i = 0;
+
+ Options *options = (Options*)malloc(sizeof(Options));
+ memset(options, 0, sizeof(Options));
+
+ for (i = 1; i < argc; i++) {
+ if (!strcmp(argv[i], "--infile") || !strcmp(argv[i], "-i")) {
+ if ((i+1) == argc) {
+ free(options);
+ return NULL;
+ }
+ options->in_file = argv[i+1];
+ i++;
+ continue;
+ }
+
+ if (!strcmp(argv[i], "--outfile") || !strcmp(argv[i], "-o")) {
+ if ((i+1) == argc) {
+ free(options);
+ return NULL;
+ }
+ options->out_file = argv[i+1];
+ i++;
+ continue;
+ }
+
+ if (!strcmp(argv[i], "--debug") || !strcmp(argv[i], "-d") || !strcmp(argv[i], "-v")) {
+ options->debug = 1;
+ }
+
+ if (!strcmp(argv[i], "--help") || !strcmp(argv[i], "-h")) {
+ free(options);
+ return NULL;
+ }
+ }
+
+ if (!options->in_file /*|| !options->out_file*/) {
+ free(options);
+ return NULL;
+ }
+
+ return options;
+}
+
+void print_usage() {
+ printf("Usage: plistutil -i|--infile in_file.plist -o|--outfile out_file.plist [--debug]\n");
+ printf("\n");
+ printf("\t-i or --infile: The file to read in.\n");
+ printf("\t-o or --outfile: The file to convert to.\n");
+ printf("\t-d, -v or --debug: Provide extended debug information.\n\n");
+}
diff --git a/dev/plutil.h b/dev/plutil.h
new file mode 100644
index 0000000..2146307
--- /dev/null
+++ b/dev/plutil.h
@@ -0,0 +1,13 @@
+
+/*
+ * main.h - header for plistutil
+ * Written by FxChiP
+ */
+
+typedef struct _options {
+ char *in_file, *out_file;
+ uint8_t debug, in_fmt, out_fmt;
+} Options;
+
+Options *parse_arguments(int argc, char *argv[]);
+void print_usage();
diff --git a/src/AFC.c b/src/AFC.c
index 54ea1bb..899bd47 100644
--- a/src/AFC.c
+++ b/src/AFC.c
@@ -245,7 +245,7 @@ static int receive_AFC_data(iphone_afc_client_t client, char **dump_here)
return retval;
}
- uint32 param1 = buffer[sizeof(AFCPacket)];
+ uint32_t param1 = buffer[sizeof(AFCPacket)];
free(buffer);
if (r_packet->operation == AFC_ERROR && !(client->afc_packet->operation == AFC_DELETE && param1 == 7)) {
@@ -474,7 +474,7 @@ iphone_error_t iphone_afc_delete_file(iphone_afc_client_t client, const char *pa
iphone_error_t iphone_afc_rename_file(iphone_afc_client_t client, const char *from, const char *to)
{
char *response = 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_t)));
int bytes = 0;
if (!client || !from || !to || !client->afc_packet || !client->connection)
@@ -660,7 +660,7 @@ iphone_afc_open_file(iphone_afc_client_t client, const char *filename,
iphone_afc_file_mode_t file_mode, iphone_afc_file_t * file)
{
iphone_afc_file_t file_loc = NULL;
- uint32 ag = 0;
+ uint32_t ag = 0;
int bytes = 0, length = 0;
char *data = (char *) malloc(sizeof(char) * (8 + strlen(filename) + 1));
@@ -795,7 +795,7 @@ iphone_afc_write_file(iphone_afc_client_t client, iphone_afc_file_t file,
{
char *acknowledgement = NULL;
const int MAXIMUM_WRITE_SIZE = 1 << 15;
- uint32 zero = 0, bytes_loc = 0, segments = (length / MAXIMUM_WRITE_SIZE), current_count = 0, i = 0;
+ uint32_t zero = 0, bytes_loc = 0, segments = (length / MAXIMUM_WRITE_SIZE), current_count = 0, i = 0;
char *out_buffer = NULL;
if (!client || !client->afc_packet || !client->connection || !file || !bytes)
@@ -812,8 +812,8 @@ iphone_afc_write_file(iphone_afc_client_t client, iphone_afc_file_t file,
client->afc_packet->entire_length = client->afc_packet->this_length + MAXIMUM_WRITE_SIZE;
client->afc_packet->operation = AFC_WRITE;
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, (char *) &file->filehandle, sizeof(uint32_t));
+ memcpy(out_buffer + 4, (char *) &zero, sizeof(uint32_t));
memcpy(out_buffer + 8, data + current_count, MAXIMUM_WRITE_SIZE);
bytes_loc = dispatch_AFC_packet(client, out_buffer, MAXIMUM_WRITE_SIZE + 8);
if (bytes_loc < 0) {
@@ -845,8 +845,8 @@ iphone_afc_write_file(iphone_afc_client_t client, iphone_afc_file_t file,
client->afc_packet->entire_length = client->afc_packet->this_length + (length - current_count);
client->afc_packet->operation = AFC_WRITE;
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, (char *) &file->filehandle, sizeof(uint32_t));
+ memcpy(out_buffer + 4, (char *) &zero, sizeof(uint32_t));
memcpy(out_buffer + 8, data + current_count, (length - current_count));
bytes_loc = dispatch_AFC_packet(client, out_buffer, (length - current_count) + 8);
free(out_buffer);
@@ -881,7 +881,7 @@ iphone_error_t iphone_afc_close_file(iphone_afc_client_t client, iphone_afc_file
if (!client || !file)
return IPHONE_E_INVALID_ARG;
char *buffer = malloc(sizeof(char) * 8);
- uint32 zero = 0;
+ uint32_t zero = 0;
int bytes = 0;
afc_lock(client);
@@ -889,8 +889,8 @@ iphone_error_t iphone_afc_close_file(iphone_afc_client_t client, iphone_afc_file
log_debug_msg("afc_close_file: File handle %i\n", file->filehandle);
// Send command
- memcpy(buffer, &file->filehandle, sizeof(uint32));
- memcpy(buffer + sizeof(uint32), &zero, sizeof(zero));
+ memcpy(buffer, &file->filehandle, sizeof(uint32_t));
+ memcpy(buffer + sizeof(uint32_t), &zero, sizeof(zero));
client->afc_packet->operation = AFC_FILE_CLOSE;
client->afc_packet->entire_length = client->afc_packet->this_length = 0;
bytes = dispatch_AFC_packet(client, buffer, sizeof(char) * 8);
@@ -926,7 +926,7 @@ iphone_error_t iphone_afc_close_file(iphone_afc_client_t client, iphone_afc_file
iphone_error_t iphone_afc_seek_file(iphone_afc_client_t client, iphone_afc_file_t file, int seekpos)
{
char *buffer = (char *) malloc(sizeof(char) * 24);
- uint32 seekto = 0, bytes = 0, zero = 0;
+ uint32_t seekto = 0, bytes = 0, zero = 0;
if (seekpos < 0)
seekpos = file->size - abs(seekpos);
@@ -935,12 +935,12 @@ iphone_error_t iphone_afc_seek_file(iphone_afc_client_t client, iphone_afc_file_
// Send the command
seekto = seekpos;
- memcpy(buffer, &file->filehandle, sizeof(uint32)); // handle
- memcpy(buffer + 4, &zero, sizeof(uint32)); // pad
- memcpy(buffer + 8, &zero, sizeof(uint32)); // fromwhere
- memcpy(buffer + 12, &zero, sizeof(uint32)); // pad
- memcpy(buffer + 16, &seekto, sizeof(uint32)); // offset
- memcpy(buffer + 20, &zero, sizeof(uint32)); // pad
+ memcpy(buffer, &file->filehandle, sizeof(uint32_t)); // handle
+ memcpy(buffer + 4, &zero, sizeof(uint32_t)); // pad
+ memcpy(buffer + 8, &zero, sizeof(uint32_t)); // fromwhere
+ memcpy(buffer + 12, &zero, sizeof(uint32_t)); // pad
+ memcpy(buffer + 16, &seekto, sizeof(uint32_t)); // offset
+ memcpy(buffer + 20, &zero, sizeof(uint32_t)); // pad
client->afc_packet->operation = AFC_FILE_SEEK;
client->afc_packet->this_length = client->afc_packet->entire_length = 0;
bytes = dispatch_AFC_packet(client, buffer, 23);
@@ -979,14 +979,14 @@ iphone_error_t iphone_afc_seek_file(iphone_afc_client_t client, iphone_afc_file_
iphone_error_t iphone_afc_truncate_file(iphone_afc_client_t client, iphone_afc_file_t file, uint32_t newsize)
{
char *buffer = (char *) malloc(sizeof(char) * 16);
- uint32 bytes = 0, zero = 0;
+ uint32_t bytes = 0, zero = 0;
afc_lock(client);
// Send command
- memcpy(buffer, &file->filehandle, sizeof(uint32)); // handle
- memcpy(buffer + 4, &zero, sizeof(uint32)); // pad
- memcpy(buffer + 8, &newsize, sizeof(uint32)); // newsize
+ memcpy(buffer, &file->filehandle, sizeof(uint32_t)); // handle
+ memcpy(buffer + 4, &zero, sizeof(uint32_t)); // pad
+ memcpy(buffer + 8, &newsize, sizeof(uint32_t)); // newsize
memcpy(buffer + 12, &zero, 3); // pad
client->afc_packet->operation = AFC_FILE_TRUNCATE;
client->afc_packet->this_length = client->afc_packet->entire_length = 0;
@@ -1012,7 +1012,7 @@ iphone_error_t iphone_afc_truncate_file(iphone_afc_client_t client, iphone_afc_f
}
}
-uint32 iphone_afc_get_file_handle(iphone_afc_file_t file)
+uint32_t iphone_afc_get_file_handle(iphone_afc_file_t file)
{
return file->filehandle;
}
diff --git a/src/AFC.h b/src/AFC.h
index 463c13e..5e4d17c 100644
--- a/src/AFC.h
+++ b/src/AFC.h
@@ -29,12 +29,12 @@
#include <glib.h>
typedef struct {
- uint32 header1, header2;
- uint32 entire_length, unknown1, this_length, unknown2, packet_num, unknown3, operation, unknown4;
+ uint32_t header1, header2;
+ uint32_t entire_length, unknown1, this_length, unknown2, packet_num, unknown3, operation, unknown4;
} AFCPacket;
typedef struct {
- uint32 filehandle, unknown1, size, unknown2;
+ uint32_t filehandle, unknown1, size, unknown2;
} AFCFilePacket;
typedef struct __AFCToken {
@@ -51,7 +51,7 @@ struct iphone_afc_client_int {
};
struct iphone_afc_file_int {
- uint32 filehandle, blocks, size, type;
+ uint32_t filehandle, blocks, size, type;
};
@@ -74,4 +74,4 @@ enum {
AFC_WRITE = 0x00000010
};
-uint32 iphone_afc_get_file_handle(iphone_afc_file_t file);
+uint32_t iphone_afc_get_file_handle(iphone_afc_file_t file);
diff --git a/src/lockdown.c b/src/lockdown.c
index 65cbf90..6b8f298 100644
--- a/src/lockdown.c
+++ b/src/lockdown.c
@@ -127,7 +127,7 @@ iphone_error_t iphone_lckd_recv(iphone_lckd_client_t client, char **dump_data, u
return IPHONE_E_INVALID_ARG;
iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
char *receive;
- uint32 datalen = 0, bytes = 0;
+ uint32_t datalen = 0, bytes = 0;
if (!client->in_SSL)
ret = iphone_mux_recv(client->connection, (char *) &datalen, sizeof(datalen), &bytes);
@@ -211,7 +211,7 @@ iphone_error_t lockdownd_hello(iphone_lckd_client_t control)
dict = add_child_to_plist(plist, "dict", "\n", NULL, 0);
key = add_key_str_dict_element(plist, dict, "Request", "QueryType", 1);
char *XML_content;
- uint32 length;
+ uint32_t length;
xmlDocDumpMemory(plist, (xmlChar **) & XML_content, &length);
ret = iphone_lckd_send(control, XML_content, length, &bytes);
@@ -265,7 +265,7 @@ iphone_error_t lockdownd_generic_get_value(iphone_lckd_client_t control, char *r
char **dictionary = NULL;
int bytes = 0, i = 0;
char *XML_content = NULL;
- uint32 length = 0;
+ uint32_t length = 0;
iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
/* Setup DevicePublicKey request plist */
@@ -420,7 +420,7 @@ iphone_error_t lockdownd_pair_device(iphone_lckd_client_t control, char *uid, ch
char **dictionary = NULL;
int bytes = 0, i = 0;
char *XML_content = NULL;
- uint32 length = 0;
+ uint32_t length = 0;
char *device_cert_b64 = NULL;
char *host_cert_b64 = NULL;
@@ -658,7 +658,7 @@ iphone_error_t lockdownd_start_SSL_session(iphone_lckd_client_t control, const c
xmlNode *dict = add_child_to_plist(plist, "dict", "\n", NULL, 0);
xmlNode *key;
char *what2send = NULL, **dictionary = NULL;
- uint32 len = 0, bytes = 0, return_me = 0, i = 0;
+ uint32_t len = 0, bytes = 0, return_me = 0, i = 0;
iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
// end variables
@@ -893,8 +893,8 @@ iphone_error_t iphone_lckd_start_service(iphone_lckd_client_t client, const char
return IPHONE_E_SSL_ERROR;
char *XML_query, **dictionary;
- uint32 length, i = 0, port_loc = 0, bytes = 0;
- uint8 result = 0;
+ uint32_t length, i = 0, port_loc = 0, bytes = 0;
+ uint8_t result = 0;
iphone_error_t ret = IPHONE_E_UNKNOWN_ERROR;
free(host_id);
diff --git a/src/plist.c b/src/plist.c
index c4d6bfa..0024577 100644
--- a/src/plist.c
+++ b/src/plist.c
@@ -23,8 +23,10 @@
#include <libxml/tree.h>
#include <string.h>
#include <assert.h>
+#include "utils.h"
#include "plist.h"
+
const char *plist_base = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n\
<plist version=\"1.0\">\n\
@@ -243,3 +245,285 @@ void free_dictionary(char **dictionary)
free(dictionary);
}
+
+/*
+ * Binary propertylist code follows
+ */
+
+
+/*
+ * This is how parsing a bplist is going to have to work:
+ * - The entire binary plist is going to have to be in memory.
+ * - A function, parse_nodes(), will have to be a recursive function
+ * which iterates over the binary plist and reads in elements into bplist_node structs
+ * and handles them accordingly. The end result should be a somewhat-hierarchical layout
+ * of bplist_nodes.
+ * - parse_nodes() will return the first node it encounters, which is usually the "root" node.
+ */
+
+uint32_t uipow(uint32_t value, uint32_t power) {
+ if (!power) return 1;
+ int i = 0, oVal = value;
+ for (i = 1; i < power; i++) {
+ value *= oVal;
+ }
+ return value;
+}
+
+void byte_convert(char *address, size_t size) {
+ int i = 0, j = 0;
+ char tmp = '\0';
+
+ for (i = 0; i < (size / 2); i++) {
+ tmp = address[i];
+ j = ((size-1) + 0) - i;
+ address[i] = address[j];
+ address[j] = tmp;
+ }
+}
+
+bplist_node *parse_raw_node(const char *bpbuffer, uint32_t bplength, uint32_t *position, uint8_t ref_size) {
+ if (!position || !bpbuffer || !bplength) return NULL;
+
+ uint8_t modifier = 0;
+ bplist_node *new_node = (bplist_node*)malloc(sizeof(bplist_node));
+ bplist_node *length_stupidity = NULL;
+ memset(new_node, 0, sizeof(bplist_node)); // initialize the new struct
+
+ int myPos = *position;
+ if (myPos == bplength || (myPos+1) == bplength) { free(new_node); return NULL; } // end of string
+
+ uint32_t length = 0;
+ if (!myPos) {
+ if (strncmp(bpbuffer, "bplist00", strlen("bplist00"))) {
+ return NULL; // badness!
+ }
+ myPos += strlen("bplist00");
+ }
+
+ // Get the node's type.
+ if (bpbuffer[myPos] == BPLIST_DATE) { // handle date separately, but do it as a real
+ // better handling of date; basically interpret as real or double
+ new_node->type = BPLIST_DATE;
+ new_node->length = 8; // always 8 for "date" (Apple intended it, not me)
+ myPos++;
+ memcpy(&new_node->realval, bpbuffer+myPos, sizeof(new_node->realval));
+ byte_convert(&new_node->realval, sizeof(new_node->realval));
+ myPos += new_node->length;
+ *position = myPos;
+ return new_node;
+ }
+
+ new_node->type = bpbuffer[myPos] & BPLIST_MASK;
+ new_node->length = bpbuffer[myPos] & BPLIST_FILL;
+ if (!new_node->type) {
+ // what? check if it's a boolean.
+ if (bpbuffer[myPos] == BPLIST_TRUE || bpbuffer[myPos] == BPLIST_FALSE) {
+ // okay, so it is. Carry on.
+ new_node->type = bpbuffer[myPos];
+ new_node->length = 0;
+ } else {
+ // er, what? we have a bad type here. Return NULL.
+ free(new_node);
+ //printf("parse_raw_node: lol type: type given %x\n", bpbuffer[myPos]);
+ return NULL;
+ }
+ }
+
+ myPos++; // puts us in the data.
+ if (new_node->length == BPLIST_FILL) { // Data happens to contain length...
+ // what? you're going to make me parse an int for the length. You suck.
+ *position = myPos;
+ length_stupidity = parse_raw_node(bpbuffer, bplength, &myPos, ref_size);
+ switch (length_stupidity->length) {
+ case sizeof(uint8_t):
+ new_node->length = length_stupidity->intval8;
+ break;
+ case sizeof(uint16_t):
+ new_node->length = length_stupidity->intval16;
+ break;
+ case sizeof(uint32_t):
+ new_node->length = length_stupidity->intval32;
+ break;
+ case sizeof(uint64_t):
+ new_node->length = length_stupidity->intval64;
+ break;
+ default:
+ free(new_node);
+ free(length_stupidity);
+ return NULL;
+ }
+ // There, we have our fucking length now.
+ *position = myPos;
+ free(length_stupidity); // cleanup
+ }
+
+ // Now we're in the data.
+ // Error-checking sorta
+ if ((myPos + new_node->length) >= bplength) {
+ new_node->length = bplength - myPos; // truncate the object
+ }
+
+ // And now for the greatest show on earth: the giant fucking switch statement.
+ switch (new_node->type) {
+ case BPLIST_INT:
+ new_node->length = uipow(2, new_node->length); // make length less misleading
+ switch (new_node->length) {
+ case sizeof(uint8_t):
+ new_node->intval8 = bpbuffer[myPos];
+ break;
+ case sizeof(uint16_t):
+ memcpy(&new_node->intval16, bpbuffer+myPos, sizeof(uint16_t));
+ new_node->intval16 = ntohs(new_node->intval16);
+ break;
+ case sizeof(uint32_t):
+ memcpy(&new_node->intval32, bpbuffer+myPos, sizeof(uint32_t));
+ new_node->intval32 = ntohl(new_node->intval32);
+ break;
+ case sizeof(uint64_t):
+ memcpy(&new_node->intval64, bpbuffer+myPos, sizeof(uint64_t));
+ byte_convert(&new_node->intval64, sizeof(uint64_t));
+ break;
+ default:
+ free(new_node);
+ printf("parse_raw_node: lol: invalid int: size given %i\n", new_node->length);
+ printf("parse_raw_node: lol: by the way sizeof(uint64) = %i\n", sizeof(uint64_t));
+ return NULL;
+ }
+ break;
+
+ case BPLIST_REAL:
+ new_node->length = uipow(2, new_node->length);
+ memcpy(&new_node->realval, bpbuffer+myPos, new_node->length); // XXX: probable buffer overflow here
+ //new_node->realval = bpbuffer[myPos]; // why not
+ byte_convert(&new_node->realval, sizeof(double));
+ break;
+
+ case BPLIST_DICT: /* returning a raw dict, it forward-references, so. */
+ new_node->length = new_node->length * 2; // dicts lie
+ case BPLIST_ARRAY: /* returning a raw array, it forward-references, so. */
+ new_node->intval8 = ref_size; // in arrays and dicts, the "ref size" alluded to in the trailer applies, and should be stored in intval8 so as to save space.
+ case BPLIST_STRING:
+ case BPLIST_DATA:
+ default: /* made to hold raw data. */
+ modifier = (new_node->intval8 > 0) ? new_node->intval8 : 1;
+ new_node->strval = (char*)malloc(sizeof(char) * (new_node->length * modifier));
+ memcpy(new_node->strval, bpbuffer+myPos, (new_node->length * modifier));
+ break;
+
+ case BPLIST_UNICODE:
+ new_node->unicodeval = (wchar_t*)malloc(sizeof(wchar_t) * new_node->length);
+ memcpy(new_node->unicodeval, bpbuffer+myPos, new_node->length);
+ break;
+ }
+
+ myPos += new_node->length;
+ *position = myPos;
+ return new_node;
+}
+
+void print_bytes(char *val, size_t size) {
+ int i = 0;
+ for (i = 0; i < size; i++) {
+ printf("Byte %i: 0x%x\n", i, val[i]);
+ }
+}
+
+bplist_node *parse_nodes(const char *bpbuffer, uint32_t bplength, uint32_t *position) {
+ bplist_node **nodeslist = NULL, **newaddr = NULL;
+ bplist_node *new_node = NULL, *root_node = NULL;
+
+ uint32_t nodeslength = 0;
+ uint8_t offset_size = 0, dict_param_size = 0;
+ offset_size = bpbuffer[bplength-26];
+ dict_param_size = bpbuffer[bplength-25];
+ uint64_t current_offset = 0;
+ //uint64_t num_objects = *(bpbuffer+(bplength-24)), root_object = *(bpbuffer+(bplength-16)), offset_table_index = *(bpbuffer+(bplength-8));
+ uint64_t num_objects = 0, root_object = 0, offset_table_index = 0;
+ memcpy(&num_objects, bpbuffer+bplength-24, sizeof(uint64_t));
+ memcpy(&root_object, bpbuffer+bplength-16, sizeof(uint64_t));
+ memcpy(&offset_table_index, bpbuffer+bplength-8, sizeof(uint64_t));
+ byte_convert(&num_objects, sizeof(uint64_t));
+ byte_convert(&root_object, sizeof(uint64_t));
+ byte_convert(&offset_table_index, sizeof(uint64_t));
+
+ log_debug_msg("Offset size: %i\nGiven: %i\n", offset_size, bpbuffer[bplength-26]);
+ log_debug_msg("Ref size: %i\nGiven: %i\n", dict_param_size, bpbuffer[bplength-25]);
+ log_debug_msg("Number of objects: %lli\nGiven: %llu\n", num_objects, *(bpbuffer+bplength-24));
+ log_debug_msg("Root object index: %lli\nGiven: %llu\n", root_object, *(bpbuffer+bplength-16));
+ log_debug_msg("Offset table index: %lli\nGiven: %llu\n", offset_table_index, *(bpbuffer+bplength-8));
+ log_debug_msg("Size of uint64: %i\n", sizeof(uint64_t));
+
+ int i = 0, j = 0, k = 0, str_i = 0, str_j = 0;
+ uint32_t index1 = 0, index2 = 0;
+
+ nodeslist = (bplist_node**)malloc(sizeof(bplist_node*) * num_objects);
+ if (!nodeslist) return NULL;
+
+ for (i = 0; i < num_objects; i++) {
+ memcpy(&current_offset, bpbuffer+(offset_table_index+(i*offset_size)), offset_size);
+ //current_offset = (offset_size == 2) ? ntohs(current_offset) : (offset_size == 4) ? ntohl(current_offset) : current_offset;
+ //if (offset_size == 8) byte_convert(&current_offset, 8);
+ byte_convert(&current_offset, (offset_size <= sizeof(current_offset)) ? offset_size : sizeof(current_offset));
+ log_debug_msg("parse_nodes: current_offset = %x\n", current_offset);
+ nodeslist[i] = parse_raw_node(bpbuffer, bplength, &current_offset, dict_param_size);
+ log_debug_msg("parse_nodes: parse_raw_node done\n");
+ }
+
+
+ for (i = 0; i < num_objects; i++) {
+ // set elements for dicts and arrays and leave the rest alone
+ log_debug_msg("parse_nodes: on node %i\n", i);
+ switch (nodeslist[i]->type) {
+ case BPLIST_DICT:
+ log_debug_msg("parse_nodes: dictionary found\n");
+ nodeslist[i]->subnodes = (bplist_node*)malloc(sizeof(bplist_node) * nodeslist[i]->length);
+ for (j = 0; j < (nodeslist[i]->length / 2); j++) {
+ str_i = j * nodeslist[i]->intval8;
+ str_j = (j + (nodeslist[i]->length / 2)) * nodeslist[i]->intval8;
+
+ memcpy(&index1, nodeslist[i]->strval+str_i, nodeslist[i]->intval8);
+ memcpy(&index2, nodeslist[i]->strval+str_j, nodeslist[i]->intval8);
+ //index1 = (dict_param_size == 1) ? index1 : (dict_param_size == 2) ? ntohs(index1) : (dict_param_size == 4) ? ntohl(index1) : index1;
+ //index2 = (dict_param_size == 1) ? index2 : (dict_param_size == 2) ? ntohs(index2) : (dict_param_size == 4) ? ntohl(index2) : index2;
+ byte_convert(&index1, (dict_param_size <= sizeof(index1)) ? dict_param_size : sizeof(index2));
+ byte_convert(&index2, (dict_param_size <= sizeof(index2)) ? dict_param_size : sizeof(index2));
+ //printf("parse_nodes: key index %i value %i\n", index1, index2);
+ //printf("parse_nodes: key type %x and length %i\n", nodeslist[index1]->type, nodeslist[index1]->length);
+ //printf("parse_nodes: value type %x and length %i\n", nodeslist[index2]->type, nodeslist[index2]->length);
+ nodeslist[i]->subnodes[k++] = nodeslist[index1];
+ nodeslist[i]->subnodes[k++] = nodeslist[index2];
+ }
+
+ nodeslist[i]->length = nodeslist[i]->length / 2;
+ free(nodeslist[i]->strval);
+ k = 0;
+ break;
+
+ case BPLIST_ARRAY:
+ log_debug_msg("parse_nodes: array found\n");
+ nodeslist[i]->subnodes = (bplist_node*)malloc(sizeof(bplist_node) * nodeslist[i]->length); // memory allocation helps a lot when storing data
+
+ for (j = 0; j < nodeslist[i]->length; j++) {
+ log_debug_msg("parse_nodes: array index %i\n", j);
+ str_j = j * nodeslist[i]->intval8;
+ //index1 = nodeslist[i]->strval[j];
+ memcpy(&index1, nodeslist[i]->strval+str_j, nodeslist[i]->intval8);
+ log_debug_msg("parse_nodes: post-memcpy\n");
+ //index1 = (dict_param_size == 1) ? index1 : (dict_param_size == 2) ? ntohs(index1) : (dict_param_size == 4) ? ntohl(index1) : index1;
+ byte_convert(&index1, (dict_param_size <= sizeof(index1)) ? dict_param_size : sizeof(index1));
+ log_debug_msg("parse_nodes: post-ntohl\nindex1 = %i\n", index1);
+ nodeslist[i]->subnodes[j] = nodeslist[index1];
+ log_debug_msg("parse_nodes: post-assignment\n");
+ }
+ free(nodeslist[i]->strval);
+ break;
+ default:
+ //printf("lol... type %x\n", nodeslist[i]->type);
+ break;
+ } // those are the only two we need to correct for.
+ }
+
+ root_node = nodeslist[root_object];
+ return root_node;
+}
diff --git a/src/plist.h b/src/plist.h
index b27a0c5..98c7d91 100644
--- a/src/plist.h
+++ b/src/plist.h
@@ -24,6 +24,12 @@
#include <libxml/parser.h>
#include <libxml/tree.h>
+#include <stdint.h>
+#include <wchar.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
xmlNode *add_key_dict_node(xmlDocPtr plist, xmlNode * dict, const char *key, const char *value, int depth);
xmlNode *add_key_str_dict_element(xmlDocPtr plist, xmlNode * dict, const char *key, const char *value, int depth);
@@ -35,4 +41,36 @@ xmlDocPtr new_plist();
char **read_dict_element_strings(xmlNode * dict);
void free_dictionary(char **dictionary);
+
+/* Binary plist stuff */
+
+enum {
+ BPLIST_TRUE = 0x08,
+ BPLIST_FALSE = 0x09,
+ BPLIST_FILL = 0x0F, /* will be used for length grabbing */
+ BPLIST_INT = 0x10,
+ BPLIST_REAL = 0x20,
+ BPLIST_DATE = 0x33,
+ BPLIST_DATA = 0x40,
+ BPLIST_STRING = 0x50,
+ BPLIST_UNICODE = 0x60,
+ BPLIST_UID = 0x70,
+ BPLIST_ARRAY = 0xA0,
+ BPLIST_SET = 0xC0,
+ BPLIST_DICT = 0xD0,
+ BPLIST_MASK = 0xF0
+};
+
+typedef struct _bplist_node {
+ struct _bplist_node *next, **subnodes; // subnodes is for arrays, dicts and (potentially) sets.
+ uint64_t length, intval64;
+ uint32_t intval32; // length = subnodes
+ uint16_t intval16;
+ uint8_t intval8;
+ uint8_t type, *indexes; // indexes for array-types; essentially specify the order in which to access for key => value pairs
+ char *strval;
+ double realval;
+ wchar_t *unicodeval;
+} bplist_node;
+
#endif
diff --git a/src/usbmux.c b/src/usbmux.c
index 2114758..f0499fa 100644
--- a/src/usbmux.c
+++ b/src/usbmux.c
@@ -37,7 +37,7 @@ static int clients = 0;
*
* @return A USBMux packet
*/
-usbmux_tcp_header *new_mux_packet(uint16 s_port, uint16 d_port)
+usbmux_tcp_header *new_mux_packet(uint16_t s_port, uint16_t d_port)
{
usbmux_tcp_header *conn = (usbmux_tcp_header *) malloc(sizeof(usbmux_tcp_header));
conn->type = htonl(6);
diff --git a/src/usbmux.h b/src/usbmux.h
index da8a361..4b18e07 100644
--- a/src/usbmux.h
+++ b/src/usbmux.h
@@ -22,6 +22,7 @@
#include <sys/types.h>
#include <stdlib.h>
#include <stdint.h>
+#include "libiphone/libiphone.h"
#ifndef USBMUX_H
#define USBMUX_H
@@ -30,17 +31,12 @@
#include "iphone.h"
#endif
-typedef uint16_t uint16;
-typedef uint32_t uint32;
-typedef uint8_t uint8;
-
-
typedef struct {
- uint32 type, length;
- uint16 sport, dport;
- uint32 scnt, ocnt;
- uint8 offset, tcp_flags;
- uint16 window, nullnull, length16;
+ uint32_t type, length;
+ uint16_t sport, dport;
+ uint32_t scnt, ocnt;
+ uint8_t offset, tcp_flags;
+ uint16_t window, nullnull, length16;
} usbmux_tcp_header;
struct iphone_umux_client_int {
@@ -50,10 +46,10 @@ struct iphone_umux_client_int {
int r_len;
};
-usbmux_tcp_header *new_mux_packet(uint16 s_port, uint16 d_port);
+usbmux_tcp_header *new_mux_packet(uint16_t s_port, uint16_t d_port);
typedef struct {
- uint32 type, length, major, minor, allnull;
+ uint32_t type, length, major, minor, allnull;
} usbmux_version_header;
usbmux_version_header *version_header();