summaryrefslogtreecommitdiff
path: root/ufilter.c
diff options
context:
space:
mode:
Diffstat (limited to 'ufilter.c')
-rw-r--r--ufilter.c108
1 files changed, 77 insertions, 31 deletions
diff --git a/ufilter.c b/ufilter.c
index 5a85b54..6d9669f 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,61 @@ 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 || isspace(*cp)) {
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) && SUHOSIN_G(upload_allow_utf8)) {
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 suhosin_log(S_FILES, "uploaded file contains binary data - file dropped");
284 } 296 if (!SUHOSIN_G(simulation)) {
297 goto continue_with_failure;
298 }
299 break;
300 }
301 }
302
303 if (SUHOSIN_G(upload_remove_binary)) {
304
305 multipart_event_file_data *mefd = (multipart_event_file_data *) event_data;
306 size_t i, j;
307 int n;
308
309 for (i=0, j=0; i<mefd->length; i++) {
310 if (mefd->data[i] >= 32 || isspace(mefd->data[i])) {
311 mefd->data[j++] = mefd->data[i];
312 } else if (SUHOSIN_G(upload_allow_utf8) && mefd->data[i] & 0x80) {
313 n = suhosin_validate_utf8_multibyte(mefd->data + i);
314 if (!n) { continue; }
315 while (n) {
316 mefd->data[j++] = mefd->data[i++];
317 n--;
318 }
319 i--;
320 }
321 }
322 mefd->data[j] = '\0';
323
324 SDEBUG("removing binary %zu %zu",i,j);
325 /* IMPORTANT FOR DAISY CHAINING */
326 mefd->length = j;
327 if (mefd->newlength) {
328 *mefd->newlength = j;
329 }
330 }
285 331
286 break; 332 break;
287 333