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
117116uint8_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