Skip to content

Commit 270f170

Browse files
committed
machine uprising
1 parent df3e895 commit 270f170

File tree

4 files changed

+783
-325
lines changed

4 files changed

+783
-325
lines changed
Lines changed: 149 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
#include <stdio.h>
32
#include <stdlib.h> /* malloc() */
43
#include <string.h> /* strncpy() */
@@ -23,7 +22,6 @@ static const char http_503[] =
2322
*
2423
* Returns:
2524
* >=0 - length of the hostname and updates *hostname
26-
* caller is responsible for freeing *hostname
2725
* -1 - Incomplete request
2826
* -2 - No Host header included in this request
2927
* -3 - Invalid hostname pointer
@@ -88,126 +86,169 @@ int next_header(const char **data, size_t *len) {
8886
return header_len;
8987
}
9088

91-
uint8_t *find_data(uint8_t *data, size_t data_len, char *value) {
89+
uint8_t *find_data(uint8_t *data, size_t data_len, const char *value) {
90+
if (!data || !value || data_len == 0)
91+
return NULL;
9292

9393
int found = 0;
9494
int value_length = strlen(value);
95-
96-
while (!found && data_len > 2) {
97-
while (data[0] != value[0] && data_len > 2) {
98-
data++;
99-
data_len--;
100-
}
101-
if (strncasecmp(value, data, value_length) == 0) {
95+
96+
// Make sure value is not longer than data
97+
if (value_length > data_len)
98+
return NULL;
99+
100+
size_t pos = 0;
101+
while (!found && pos + value_length <= data_len) {
102+
if (strncasecmp((char *)&data[pos], value, value_length) == 0) {
102103
found = 1;
103-
} else {
104-
data++;
105-
data_len--;
104+
return &data[pos];
106105
}
107-
}
108-
if (found) {
109-
return data;
106+
pos++;
110107
}
111108

112-
return 0;
109+
return NULL;
113110
}
114111

115-
uint_t patch_buffer[2*MTU];
112+
// Static buffer for HTTP patching with safe size (avoid global array overflows)
113+
// Using 2*MTU ensures we have enough space for the original request plus any additions
114+
static uint8_t patch_buffer[2*MTU];
116115

117116
uint8_t *patch_http_url(uint8_t *data, size_t *data_len) {
118-
__android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, "patch_http_url start");
119-
120-
char hostname[1024];
121-
uint8_t *host = find_data(data, *data_len, "Host: ");
122-
size_t length = 0;
123-
if (host) {
124-
host += 6;
125-
while (*host != '\r' && length < 511) {
126-
hostname[length] = *host;
127-
host++;
128-
length++;
129-
}
130-
} else {
131-
LOG("patch_http_url no host");
132-
return 0;
117+
if (!data || !data_len || *data_len == 0 || *data_len > MTU) {
118+
LOG("patch_http_url: Invalid input data");
119+
return NULL;
133120
}
134121

135-
__android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, "patch_http_url find word");
136-
137-
//GET POST PUT DELETE HEAD OPTIONS PATCH
138-
char *word;
139-
uint8_t *pos = 0;
140-
if ((pos = find_data(data, *data_len, "GET ")) > 0) {
141-
word = "GET ";
142-
} else if ((pos = find_data(data, *data_len, "POST ")) > 0) {
143-
word = "POST ";
144-
} else if ((pos = find_data(data, *data_len, "PUT ")) > 0) {
145-
word = "PUT ";
146-
} else if ((pos = find_data(data, *data_len, "DELETE ")) > 0) {
147-
word = "DELETE ";
148-
} else if ((pos = find_data(data, *data_len, "HEAD ")) > 0) {
149-
word = "HEAD ";
150-
} else if ((pos = find_data(data, *data_len, "OPTIONS ")) > 0) {
151-
word = "OPTIONS ";
152-
} else if ((pos = find_data(data, *data_len, "PATCH ")) > 0) {
153-
word = "PATCH ";
154-
} else if ((pos = find_data(data, *data_len, "HEAD ")) > 0) {
155-
word = "HEAD ";
156-
} else if ((pos = find_data(data, *data_len, "TRACE ")) > 0) {
157-
word = "TRACE ";
158-
} else if ((pos = find_data(data, *data_len, "PROPFIND ")) > 0) {
159-
word = "PROPFIND ";
160-
} else if ((pos = find_data(data, *data_len, "PROPPATCH ")) > 0) {
161-
word = "PROPPATCH ";
162-
} else if ((pos = find_data(data, *data_len, "MKCOL ")) > 0) {
163-
word = "MKCOL ";
164-
} else if ((pos = find_data(data, *data_len, "COPY ")) > 0) {
165-
word = "COPY ";
166-
} else if ((pos = find_data(data, *data_len, "MOVE ")) > 0) {
167-
word = "MOVE ";
168-
} else if ((pos = find_data(data, *data_len, "LOCK ")) > 0) {
169-
word = "LOCK ";
170-
} else if ((pos = find_data(data, *data_len, "UNLOCK ")) > 0) {
171-
word = "UNLOCK ";
172-
} else if ((pos = find_data(data, *data_len, "LINK ")) > 0) {
173-
word = "LINK ";
174-
} else if ((pos = find_data(data, *data_len, "UNLINK "))> 0) {
175-
word = "UNLINK ";
176-
}
122+
__android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, "patch_http_url start (data length: %zu)", *data_len);
177123

178-
if (!pos) {
179-
LOG("patch_http_url no word");
180-
return 0;
124+
// Extract hostname from Host header
125+
char hostname[512] = {0};
126+
uint8_t *host_header = find_data(data, *data_len, "Host: ");
127+
if (!host_header) {
128+
LOG("patch_http_url: No Host header found");
129+
return NULL;
181130
}
182-
183-
184-
size_t http_len = strlen("http://");
185-
size_t word_len = strlen(word);
186-
size_t pos1 = pos - data + word_len;
187-
188-
LOG("patch_http_url word found");
189-
190-
if (data[pos1] == 'h' &&
191-
data[pos1 + 1] == 't' &&
192-
data[pos1 + 2] == 't' &&
193-
data[pos1 + 3] == 'p' &&
194-
data[pos1 + 4] == ':') {
195-
196-
LOG("patch_http_url already patched");
197-
return 0;
131+
132+
// Extract hostname from header (skip "Host: " and stop at CR or space)
133+
host_header += 6; // Skip "Host: "
134+
size_t hostname_len = 0;
135+
size_t max_offset = *data_len - (host_header - data);
136+
137+
while (hostname_len < sizeof(hostname) - 1 &&
138+
hostname_len < max_offset &&
139+
host_header[hostname_len] != '\r' &&
140+
host_header[hostname_len] != '\n' &&
141+
host_header[hostname_len] != ' ') {
142+
hostname[hostname_len] = host_header[hostname_len];
143+
hostname_len++;
198144
}
199-
200-
uint8_t *new_data = &patch_buffer[0];
201-
LOG("patch_http_url start patch");
202-
memcpy(new_data, data, pos1);
203-
204-
memcpy(new_data + pos1, "http://", http_len);
205-
memcpy(new_data + pos1 + http_len, hostname, length);
206-
memcpy(new_data + pos1 + http_len + length, data + pos1, *data_len - pos1);
207-
208-
*data_len += http_len + length;
209-
210-
LOG("patch_http_url end patch");
211-
145+
hostname[hostname_len] = '\0';
146+
147+
if (hostname_len == 0) {
148+
LOG("patch_http_url: Empty hostname");
149+
return NULL;
150+
}
151+
152+
__android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, "patch_http_url: Found hostname: %s", hostname);
153+
154+
// Find HTTP method
155+
const char *http_methods[] = {
156+
"GET ", "POST ", "PUT ", "DELETE ", "HEAD ", "OPTIONS ",
157+
"PATCH ", "TRACE ", "CONNECT ", "PROPFIND ", "PROPPATCH ",
158+
"MKCOL ", "COPY ", "MOVE ", "LOCK ", "UNLOCK ", "LINK ", "UNLINK "
159+
};
160+
161+
uint8_t *method_pos = NULL;
162+
const char *method_str = NULL;
163+
size_t method_len = 0;
164+
165+
for (size_t i = 0; i < sizeof(http_methods) / sizeof(http_methods[0]); i++) {
166+
uint8_t *pos = find_data(data, *data_len, http_methods[i]);
167+
if (pos) {
168+
method_pos = pos;
169+
method_str = http_methods[i];
170+
method_len = strlen(method_str);
171+
break;
172+
}
173+
}
174+
175+
if (!method_pos) {
176+
LOG("patch_http_url: No HTTP method found");
177+
return NULL;
178+
}
179+
180+
__android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, "patch_http_url: Found method: %s", method_str);
181+
182+
// Find the URL part (after the method)
183+
size_t url_offset = method_pos - data + method_len;
184+
if (url_offset >= *data_len) {
185+
LOG("patch_http_url: URL parsing error");
186+
return NULL;
187+
}
188+
189+
// Check if URL already starts with http://
190+
if (*data_len > url_offset + 7 &&
191+
strncasecmp((char*)&data[url_offset], "http://", 7) == 0) {
192+
LOG("patch_http_url: URL already has http://");
193+
return NULL;
194+
}
195+
196+
// Check if URL already starts with https://
197+
if (*data_len > url_offset + 8 &&
198+
strncasecmp((char*)&data[url_offset], "https://", 8) == 0) {
199+
LOG("patch_http_url: URL already has https://");
200+
return NULL;
201+
}
202+
203+
// Check if URL is a relative path (starts with / or ./)
204+
bool is_relative = (*data_len > url_offset &&
205+
(data[url_offset] == '/' ||
206+
(data[url_offset] == '.' && *data_len > url_offset + 1 && data[url_offset + 1] == '/')));
207+
208+
// Calculate new data length and ensure it fits in our buffer
209+
size_t http_prefix_len = 7; // "http://"
210+
size_t new_data_len = 0;
211+
212+
if (is_relative) {
213+
// For relative URLs, we need: [beginning][http://hostname][relative_path][rest]
214+
new_data_len = url_offset + http_prefix_len + hostname_len + (*data_len - url_offset);
215+
} else {
216+
// For absolute URLs, we need: [beginning][http://hostname/][absolute_path][rest]
217+
new_data_len = url_offset + http_prefix_len + hostname_len + 1 + (*data_len - url_offset);
218+
}
219+
220+
if (new_data_len > sizeof(patch_buffer)) {
221+
LOG("patch_http_url: New data too large for buffer");
222+
return NULL;
223+
}
224+
225+
// Create the patched request
226+
uint8_t *new_data = patch_buffer;
227+
228+
// Copy everything up to the URL
229+
memcpy(new_data, data, url_offset);
230+
231+
// Add http:// and hostname
232+
memcpy(new_data + url_offset, "http://", http_prefix_len);
233+
memcpy(new_data + url_offset + http_prefix_len, hostname, hostname_len);
234+
235+
// Handle relative vs absolute URL
236+
if (is_relative) {
237+
// For relative URLs, just append the URL as-is
238+
memcpy(new_data + url_offset + http_prefix_len + hostname_len,
239+
data + url_offset, *data_len - url_offset);
240+
} else {
241+
// For absolute URLs, add a slash after hostname
242+
new_data[url_offset + http_prefix_len + hostname_len] = '/';
243+
244+
// Then add the absolute URL
245+
memcpy(new_data + url_offset + http_prefix_len + hostname_len + 1,
246+
data + url_offset, *data_len - url_offset);
247+
}
248+
249+
// Update data length
250+
*data_len = new_data_len;
251+
252+
__android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, "patch_http_url: Successfully patched URL");
212253
return new_data;
213-
};
254+
};

0 commit comments

Comments
 (0)