Skip to content

Commit e2ff112

Browse files
FxChiPmcolyer
authored andcommitted
First released version, 0.089.
0 parents  commit e2ff112

File tree

13 files changed

+1354
-0
lines changed

13 files changed

+1354
-0
lines changed

AFC.c

Lines changed: 279 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,279 @@
1+
/*
2+
* AFC.c -- contains functions for the built-in AFC client.
3+
* Written by FxChiP
4+
*/
5+
6+
#include "AFC.h"
7+
8+
extern int debug;
9+
10+
AFClient *afc_connect(iPhone *phone, int s_port, int d_port) {
11+
if (!phone) return NULL;
12+
AFClient *client = (AFClient*)malloc(sizeof(AFClient));
13+
client->connection = mux_connect(phone, s_port, d_port);
14+
if (!client->connection) { free(client); return NULL; }
15+
else {
16+
client->afc_packet = (AFCPacket*)malloc(sizeof(AFCPacket));
17+
if (client->afc_packet) {
18+
client->phone = phone;
19+
client->afc_packet->packet_num = 0;
20+
client->afc_packet->unknown1 = client->afc_packet->unknown2 = client->afc_packet->unknown3 = client->afc_packet->unknown4 = 0;
21+
client->afc_packet->header1 = 0x36414643;
22+
client->afc_packet->header2 = 0x4141504C;
23+
client->file_handle = 0;
24+
return client;
25+
} else {
26+
mux_close_connection(client->phone, client->connection);
27+
free(client);
28+
return NULL;
29+
}
30+
}
31+
32+
return NULL; // should never get to this point
33+
}
34+
35+
void afc_disconnect(AFClient *client) {
36+
// client and its members should never be NULL is assumed here.
37+
if (!client || !client->connection || !client->phone || !client->afc_packet) return;
38+
mux_close_connection(client->phone, client->connection);
39+
free(client->afc_packet);
40+
free(client);
41+
}
42+
43+
int count_nullspaces(char *string, int number) {
44+
int i = 0, nulls = 0;
45+
for (i = 0; i < number; i++) {
46+
if (string[i] == '\0') nulls++;
47+
}
48+
return nulls;
49+
}
50+
51+
int dispatch_AFC_packet(AFClient *client, char *data, int length) {
52+
char *buffer;
53+
int bytes = 0;
54+
if (!client || !client->connection || !client->phone || !client->afc_packet) return 0;
55+
if (!data || !length) length = 0;
56+
57+
client->afc_packet->packet_num++;
58+
client->afc_packet->entire_length = client->afc_packet->this_length = (length) ? sizeof(AFCPacket) + length + 1 : sizeof(AFCPacket);
59+
60+
if (!length) {
61+
bytes = mux_send(client->phone, client->connection, (char*)client->afc_packet, client->afc_packet->this_length);
62+
if (bytes <= 0) return 0;
63+
else return bytes;
64+
} else {
65+
buffer = (char*)malloc(sizeof(char) * client->afc_packet->this_length);
66+
memcpy(buffer, client->afc_packet, sizeof(AFCPacket));
67+
memcpy(buffer+sizeof(AFCPacket), data, length);
68+
buffer[client->afc_packet->this_length-1] = '\0';
69+
70+
bytes = mux_send(client->phone, client->connection, buffer, client->afc_packet->this_length);
71+
free(buffer); // don't need it
72+
if (bytes <= 0) return 0;
73+
else return bytes;
74+
}
75+
76+
return 0;
77+
}
78+
79+
int receive_AFC_data(AFClient *client, char **dump_here) {
80+
AFCPacket *r_packet;
81+
char *buffer = (char*)malloc(sizeof(AFCPacket) * 4);
82+
int bytes = 0, recv_len = 0;
83+
84+
bytes = mux_recv(client->phone, client->connection, buffer, sizeof(AFCPacket) * 4);
85+
if (bytes <= 0) {
86+
free(buffer);
87+
printf("Just didn't get enough.\n");
88+
*dump_here = NULL;
89+
return 0;
90+
}
91+
92+
r_packet = (AFCPacket*)malloc(sizeof(AFCPacket));
93+
memcpy(r_packet, buffer, sizeof(AFCPacket));
94+
95+
if (r_packet->entire_length == r_packet->this_length && r_packet->entire_length > sizeof(AFCPacket) && r_packet->operation != AFC_ERROR) {
96+
*dump_here = (char*)malloc(sizeof(char) * (r_packet->entire_length-sizeof(AFCPacket)));
97+
memcpy(*dump_here, buffer+sizeof(AFCPacket), r_packet->entire_length-sizeof(AFCPacket));
98+
free(buffer);
99+
free(r_packet);
100+
return r_packet->entire_length - sizeof(AFCPacket);
101+
}
102+
103+
uint32 param1 = buffer[sizeof(AFCPacket)];
104+
free(buffer);
105+
106+
if (r_packet->operation == 0x01) {
107+
printf("Oops? Bad operation code received.\n");
108+
if (param1 == 0) printf("... false alarm, but still\n");
109+
else printf("Errno %i\n", param1);
110+
free(r_packet);
111+
*dump_here = NULL;
112+
return 0;
113+
} else {
114+
printf("Operation code %x\nFull length %i and this length %i\n", r_packet->operation, r_packet->entire_length, r_packet->this_length);
115+
}
116+
117+
recv_len = r_packet->entire_length - r_packet->this_length;
118+
free(r_packet);
119+
buffer = (char*)malloc(sizeof(char) * recv_len);
120+
bytes = mux_recv(client->phone, client->connection, buffer, recv_len);
121+
if (bytes <= 0) {
122+
free(buffer);
123+
printf("Didn't get it at the second pass.\n");
124+
*dump_here = NULL;
125+
return 0;
126+
}
127+
128+
*dump_here = buffer; // what they do beyond this point = not my problem
129+
return bytes;
130+
}
131+
132+
char **afc_get_dir_list(AFClient *client, char *dir) {
133+
client->afc_packet->operation = AFC_LIST_DIR;
134+
int bytes = 0;
135+
char *blah = NULL, **list = NULL;
136+
bytes = dispatch_AFC_packet(client, dir, strlen(dir));
137+
if (!bytes) return NULL;
138+
139+
bytes = receive_AFC_data(client, &blah);
140+
if (!bytes && !blah) return NULL;
141+
142+
list = make_strings_list(blah, bytes);
143+
free(blah);
144+
return list;
145+
}
146+
147+
char **make_strings_list(char *tokens, int true_length) {
148+
if (!tokens || !true_length) return NULL;
149+
int nulls = 0, i = 0, j = 0;
150+
char **list = NULL;
151+
152+
nulls = count_nullspaces(tokens, true_length);
153+
list = (char**)malloc(sizeof(char*) * (nulls + 1));
154+
for (i = 0; i < nulls; i++) {
155+
list[i] = strdup(tokens+j);
156+
j += strlen(list[i]) + 1;
157+
}
158+
list[i] = strdup("");
159+
return list;
160+
}
161+
162+
AFCFile *afc_get_file_info(AFClient *client, char *path) {
163+
client->afc_packet->operation = AFC_GET_INFO;
164+
dispatch_AFC_packet(client, path, strlen(path));
165+
166+
char *received, **list;
167+
AFCFile *my_file;
168+
int length, i = 0;
169+
170+
length = receive_AFC_data(client, &received);
171+
list = make_strings_list(received, length);
172+
free(received);
173+
if (list) {
174+
my_file = (AFCFile *)malloc(sizeof(AFCFile));
175+
for (i = 0; strcmp(list[i], ""); i++) {
176+
if (!strcmp(list[i], "st_size")) {
177+
my_file->size = atoi(list[i+1]);
178+
}
179+
180+
181+
if (!strcmp(list[i], "st_blocks")) {
182+
my_file->blocks = atoi(list[i+1]);
183+
}
184+
185+
if (!strcmp(list[i], "st_ifmt")) {
186+
if (!strcmp(list[i+1], "S_IFREG")) {
187+
my_file->type = S_IFREG;
188+
} else if (!strcmp(list[i+1], "S_IFDIR")) {
189+
my_file->type = S_IFDIR;
190+
}
191+
}
192+
}
193+
free_dictionary(list);
194+
return my_file;
195+
} else {
196+
return NULL;
197+
}
198+
}
199+
200+
AFCFile *afc_open_file(AFClient *client, const char *filename, uint32 file_mode) {
201+
if (file_mode != AFC_FILE_READ && file_mode != AFC_FILE_WRITE) return NULL;
202+
if (!client ||!client->connection || !client->phone ||!client->afc_packet) return NULL;
203+
char *further_data = (char*)malloc(sizeof(char) * (8 + strlen(filename) + 1));
204+
AFCFile *file_infos = NULL;
205+
memcpy(further_data, &file_mode, 4);
206+
uint32 ag = 0;
207+
memcpy(further_data+4, &ag, 4);
208+
memcpy(further_data+8, filename, strlen(filename));
209+
further_data[8+strlen(filename)] = '\0';
210+
int bytes = 0, length_thing = 0;
211+
client->afc_packet->operation = AFC_FILE_OPEN;
212+
213+
bytes = dispatch_AFC_packet(client, further_data, 8+strlen(filename));
214+
free(further_data);
215+
if (bytes <= 0) {
216+
printf("didn't read enough\n");
217+
return NULL;
218+
} else {
219+
printf("O HAI\n");
220+
length_thing = receive_AFC_data(client, &further_data);
221+
if (length_thing && further_data) {
222+
printf("ARA\n");
223+
file_infos = afc_get_file_info(client, filename);
224+
memcpy(&file_infos->filehandle, further_data, 4);
225+
printf("gr\n");
226+
return file_infos;
227+
} else {
228+
printf("didn't get further data or something\n");
229+
return NULL;
230+
}
231+
}
232+
printf("what the fuck\n");
233+
return NULL;
234+
}
235+
236+
int afc_read_file(AFClient *client, AFCFile *file, char *data, int length) {
237+
if (!client || !client->afc_packet || !client->phone || !client->connection || !file) return -1;
238+
AFCFilePacket *packet = (AFCFilePacket*)malloc(sizeof(AFCFilePacket));
239+
char *input = NULL;
240+
packet->unknown1 = packet->unknown2 = 0;
241+
packet->filehandle = file->filehandle;
242+
packet->size = length;
243+
int bytes = 0;
244+
245+
client->afc_packet->operation = AFC_READ;
246+
bytes = dispatch_AFC_packet(client, packet, sizeof(AFCFilePacket));
247+
248+
if (bytes > 0) {
249+
bytes = receive_AFC_data(client, &input);
250+
if (bytes <= 0) {
251+
return -1;
252+
} else {
253+
memcpy(data, input, (bytes > length) ? length : bytes);
254+
return (bytes > length) ? length : bytes;
255+
}
256+
} else {
257+
return -1;
258+
}
259+
return 0;
260+
}
261+
262+
void afc_close_file(AFClient *client, AFCFile *file) {
263+
char *buffer = malloc(sizeof(char) * 8);
264+
uint32 zero = 0;
265+
if (debug) printf("File handle %i\n", file->filehandle);
266+
memcpy(buffer, &file->filehandle, sizeof(uint32));
267+
memcpy(buffer, &zero, sizeof(zero));
268+
client->afc_packet->operation = AFC_FILE_CLOSE;
269+
int bytes = 0;
270+
bytes = dispatch_AFC_packet(client, buffer, sizeof(char) * 8);
271+
free(buffer);
272+
if (!bytes) return;
273+
274+
bytes = receive_AFC_data(client, &buffer);
275+
if (bytes<=0 && !buffer) printf("closefile: all went as expected\n");
276+
else { printf("We have a buffer!??!?\nLength %i\n", bytes); fwrite(buffer, 1, bytes, stdout); printf("\n"); }
277+
if (buffer) free(buffer); // we're *SUPPOSED* to get an "error" here.
278+
}
279+

AFC.h

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
* AFC.h
3+
* Defines and structs and the like for the built-in AFC client
4+
* Written by FxChiP
5+
*/
6+
7+
#include "usbmux.h"
8+
#include "iphone.h"
9+
10+
#include <string.h>
11+
#include <stdio.h>
12+
#include <stdlib.h>
13+
14+
typedef struct {
15+
//const uint32 header1 = 0x36414643; // '6AFC' or 'CFA6' when sent ;)
16+
uint32 header1, header2;
17+
//const uint32 header2 = 0x4141504C; // 'AAPL' or 'LPAA' when sent ;)
18+
uint32 entire_length, unknown1, this_length, unknown2, packet_num, unknown3, operation, unknown4;
19+
} AFCPacket;
20+
21+
typedef struct {
22+
usbmux_tcp_header *connection;
23+
iPhone *phone;
24+
AFCPacket *afc_packet;
25+
int file_handle;
26+
} AFClient;
27+
28+
typedef struct {
29+
uint32 filehandle, unknown1, size, unknown2;
30+
} AFCFilePacket;
31+
32+
typedef struct {
33+
uint32 filehandle, blocks, size, type;
34+
} AFCFile;
35+
36+
typedef struct __AFCToken {
37+
struct __AFCToken *last, *next;
38+
char *token;
39+
} AFCToken;
40+
41+
enum {
42+
S_IFREG = 0,
43+
S_IFDIR = 1
44+
};
45+
46+
enum {
47+
AFC_FILE_READ = 0x00000002,
48+
AFC_FILE_WRITE = 0x00000003
49+
};
50+
51+
enum {
52+
AFC_ERROR = 0x00000001,
53+
AFC_GET_INFO = 0x0000000a,
54+
AFC_GET_DEVINFO = 0x0000000b,
55+
AFC_LIST_DIR = 0x00000003,
56+
AFC_SUCCESS_RESPONSE = 0x00000002,
57+
AFC_FILE_OPEN = 0x0000000d,
58+
AFC_FILE_CLOSE = 0x00000014,
59+
AFC_FILE_HANDLE = 0x0000000e,
60+
AFC_READ = 0x0000000f
61+
};
62+
63+
AFClient *afc_connect(iPhone *phone, int s_port, int d_port);
64+
void afc_disconnect(AFClient *client);
65+
int count_nullspaces(char *string, int number);
66+
char **make_strings_list(char *tokens, int true_length);
67+
int dispatch_AFC_packet(AFClient *client, char *data, int length);
68+
int receive_AFC_data(AFClient *client, char **dump_here);
69+
70+
char **afc_get_dir_list(AFClient *client, char *dir);
71+
AFCFile *afc_get_file_info(AFClient *client, char *path);
72+
AFCFile *afc_open_file(AFClient *client, const char *filename, uint32 file_mode);
73+
void afc_close_file(AFClient *client, AFCFile *file);
74+
int afc_read_file(AFClient *client, AFCFile *file, char *data, int length);

buildme.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
gcc `xml2-config --cflags --libs` -o main usbmux.c main.c iphone.c plist.c lockdown.c AFC.c -lusb -lgnutls

0 commit comments

Comments
 (0)