summaryrefslogtreecommitdiff
path: root/ufilter.c
diff options
context:
space:
mode:
Diffstat (limited to 'ufilter.c')
-rw-r--r--ufilter.c112
1 files changed, 81 insertions, 31 deletions
diff --git a/ufilter.c b/ufilter.c
index 5a85b54..2eeed56 100644
--- a/ufilter.c
+++ b/ufilter.c
@@ -197,6 +197,29 @@ return_failure:
197} 197}
198/* }}} */ 198/* }}} */
199 199
200static inline int suhosin_validate_utf8_multibyte(const char* cp)
201{
202 if ((*cp & 0xe0) == 0xc0 && // 1st byte is 110xxxxx
203 (*(cp+1) & 0xc0) == 0x80 && // 2nd byte is 10xxxxxx
204 (*cp & 0x1e)) { // overlong check 110[xxxx]x 10xxxxxx
205 return 2;
206 }
207 if ((*cp & 0xf0) == 0xe0 && // 1st byte is 1110xxxx
208 (*(cp+1) & 0xc0) == 0x80 && // 2nd byte is 10xxxxxx
209 (*(cp+2) & 0xc0) == 0x80 && // 3rd byte is 10xxxxxx
210 ((*cp & 0x0f) | (*(cp+1) & 0x20))) { // 1110[xxxx] 10[x]xxxxx 10xxxxxx
211 return 3;
212 }
213 if ((*cp & 0xf8) == 0xf0 && // 1st byte is 11110xxx
214 (*(cp+1) & 0xc0) == 0x80 && // 2nd byte is 10xxxxxx
215 (*(cp+2) & 0xc0) == 0x80 && // 3rd byte is 10xxxxxx
216 (*(cp+3) & 0xc0) == 0x80 && // 4th byte is 10xxxxxx
217 ((*cp & 0x07) | (*(cp+1) & 0x30))) { // 11110[xxx] 10[xx]xxxx 10xxxxxx 10xxxxxx
218 return 4;
219 }
220 return 0;
221}
222
200int suhosin_rfc1867_filter(unsigned int event, void *event_data, void **extra TSRMLS_DC) 223int suhosin_rfc1867_filter(unsigned int event, void *event_data, void **extra TSRMLS_DC)
201{ 224{
202 int retval = SUCCESS; 225 int retval = SUCCESS;
@@ -250,38 +273,65 @@ int suhosin_rfc1867_filter(unsigned int event, void *event_data, void **extra TS
250 } 273 }
251 } 274 }
252 275
253 if (SUHOSIN_G(upload_disallow_binary)) { 276 if (SUHOSIN_G(upload_disallow_binary)) {
254 277
255 multipart_event_file_data *mefd = (multipart_event_file_data *) event_data; 278 multipart_event_file_data *mefd = (multipart_event_file_data *) event_data;
256 size_t i;
257
258 for (i=0; i<mefd->length; i++) {
259 if (mefd->data[i] < 32 && !isspace(mefd->data[i])) {
260 suhosin_log(S_FILES, "uploaded file contains binary data - file dropped");
261 if (!SUHOSIN_G(simulation)) {
262 goto continue_with_failure;
263 }
264 }
265 }
266 }
267 279
268 if (SUHOSIN_G(upload_remove_binary)) { 280 char *cp, *cpend;
269 281 int n;
270 multipart_event_file_data *mefd = (multipart_event_file_data *) event_data; 282 cpend = mefd->data + mefd->length;
271 size_t i, j; 283 for (char *cp = mefd->data; cp < cpend; cp++) {
272 284 if (*cp >= 32) {
273 for (i=0, j=0; i<mefd->length; i++) { 285 continue;
274 if (mefd->data[i] >= 32 || isspace(mefd->data[i])) { 286 }
275 mefd->data[j++] = mefd->data[i]; 287 if (*cp & 0x80) {
276 } 288 SDEBUG("checking char %x", *cp);
277 } 289 if ((n = suhosin_validate_utf8_multibyte(cp))) { // valid UTF8 multibyte character
278 SDEBUG("removing binary %u %u",i,j); 290 cp += n - 1;
279 /* IMPORTANT FOR DAISY CHAINING */ 291 continue;
280 mefd->length = j; 292 }
281 if (mefd->newlength) { 293 }
282 *mefd->newlength = j; 294
283 } 295 if (!isspace(*cp)) {
284 } 296 suhosin_log(S_FILES, "uploaded file contains binary data - file dropped");
297 if (!SUHOSIN_G(simulation)) {
298 goto continue_with_failure;
299 }
300 break;
301 }
302
303 }
304
305 }
306
307 if (SUHOSIN_G(upload_remove_binary)) {
308
309 multipart_event_file_data *mefd = (multipart_event_file_data *) event_data;
310 size_t i, j;
311 int n;
312
313 for (i=0, j=0; i<mefd->length; i++) {
314 if (mefd->data[i] >= 32 || isspace(mefd->data[i])) {
315 mefd->data[j++] = mefd->data[i];
316 } else if (mefd->data[i] & 0x80) {
317 n = suhosin_validate_utf8_multibyte(mefd->data + i);
318 if (!n) { continue; }
319 while (n) {
320 mefd->data[j++] = mefd->data[i++];
321 n--;
322 }
323 i--;
324 }
325 }
326 mefd->data[j] = '\0';
327
328 SDEBUG("removing binary %zu %zu",i,j);
329 /* IMPORTANT FOR DAISY CHAINING */
330 mefd->length = j;
331 if (mefd->newlength) {
332 *mefd->newlength = j;
333 }
334 }
285 335
286 break; 336 break;
287 337