summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Fuhrmannek2014-10-11 10:25:59 +0200
committerBen Fuhrmannek2014-10-11 10:25:59 +0200
commitc8724cde260e6c8bab4aefffffa1aa46f92a57ee (patch)
treefa71c2fd8f6c1e84ea2b23e5040253bf1ce93825
parent3159694378333c08c73d4fcd4b73725c02249750 (diff)
fixed utf8 detection + made feature experimental
-rw-r--r--php_suhosin.h2
-rw-r--r--suhosin.c4
-rw-r--r--suhosin.ini10
-rw-r--r--tests/filter/suhosin_upload_disallow_binary_utf8.phpt4
-rw-r--r--tests/filter/suhosin_upload_disallow_binary_utf8fail.phpt4
-rw-r--r--tests/filter/suhosin_upload_remove_binary_utf8.phpt4
-rw-r--r--tests/filter/suhosin_upload_remove_binary_utf8fail.phpt4
-rw-r--r--ufilter.c22
8 files changed, 34 insertions, 20 deletions
diff --git a/php_suhosin.h b/php_suhosin.h
index d567877..df7c877 100644
--- a/php_suhosin.h
+++ b/php_suhosin.h
@@ -250,7 +250,9 @@ ZEND_BEGIN_MODULE_GLOBALS(suhosin)
250 zend_bool upload_disallow_elf; 250 zend_bool upload_disallow_elf;
251 zend_bool upload_disallow_binary; 251 zend_bool upload_disallow_binary;
252 zend_bool upload_remove_binary; 252 zend_bool upload_remove_binary;
253#ifdef SUHOSIN_EXPERIMENTAL
253 zend_bool upload_allow_utf8; 254 zend_bool upload_allow_utf8;
255#endif
254 char *upload_verification_script; 256 char *upload_verification_script;
255 257
256 zend_bool no_more_variables; 258 zend_bool no_more_variables;
diff --git a/suhosin.c b/suhosin.c
index fc84a94..8d25acc 100644
--- a/suhosin.c
+++ b/suhosin.c
@@ -824,7 +824,9 @@ PHP_INI_BEGIN()
824 STD_PHP_INI_ENTRY("suhosin.upload.disallow_elf", "1", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateUploadBool, upload_disallow_elf, zend_suhosin_globals, suhosin_globals) 824 STD_PHP_INI_ENTRY("suhosin.upload.disallow_elf", "1", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateUploadBool, upload_disallow_elf, zend_suhosin_globals, suhosin_globals)
825 STD_PHP_INI_ENTRY("suhosin.upload.disallow_binary", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateUploadBool, upload_disallow_binary, zend_suhosin_globals, suhosin_globals) 825 STD_PHP_INI_ENTRY("suhosin.upload.disallow_binary", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateUploadBool, upload_disallow_binary, zend_suhosin_globals, suhosin_globals)
826 STD_PHP_INI_ENTRY("suhosin.upload.remove_binary", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateUploadBool, upload_remove_binary, zend_suhosin_globals, suhosin_globals) 826 STD_PHP_INI_ENTRY("suhosin.upload.remove_binary", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateUploadBool, upload_remove_binary, zend_suhosin_globals, suhosin_globals)
827 STD_PHP_INI_ENTRY("suhosin.upload.allow_utf8", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateUploadBool, upload_allow_utf8, zend_suhosin_globals, suhosin_globals) 827#ifdef SUHOSIN_EXPERIMENTAL
828 STD_PHP_INI_BOOLEAN("suhosin.upload.allow_utf8", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateUploadBool, upload_allow_utf8, zend_suhosin_globals, suhosin_globals)
829#endif
828 STD_PHP_INI_ENTRY("suhosin.upload.verification_script", NULL, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateUploadString, upload_verification_script, zend_suhosin_globals, suhosin_globals) 830 STD_PHP_INI_ENTRY("suhosin.upload.verification_script", NULL, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateUploadString, upload_verification_script, zend_suhosin_globals, suhosin_globals)
829 831
830 832
diff --git a/suhosin.ini b/suhosin.ini
index 3ae8ff5..311bca7 100644
--- a/suhosin.ini
+++ b/suhosin.ini
@@ -105,9 +105,6 @@
105; | LOG_LOCAL7 | 31 | 105; | LOG_LOCAL7 | 31 |
106; +--------------+-------+ 106; +--------------+-------+
107; 107;
108; Using constant names is only supported with the Suhosin-Patch. If in doubt, use
109; the numeric value.
110;
111;suhosin.log.syslog.facility = LOG_USER 108;suhosin.log.syslog.facility = LOG_USER
112; 109;
113 110
@@ -141,9 +138,6 @@
141; |LOG_ERR | 7 | 138; |LOG_ERR | 7 |
142; +------------+-------+ 139; +------------+-------+
143; 140;
144; Using constant names is only supported with the Suhosin-Patch. If in doubt, use
145; the numeric value.
146;
147;suhosin.log.syslog.priority = LOG_ALERT 141;suhosin.log.syslog.priority = LOG_ALERT
148; 142;
149 143
@@ -1325,8 +1319,8 @@
1325; * Type: Boolean 1319; * Type: Boolean
1326; * Default: Off 1320; * Default: Off
1327; 1321;
1328; This option allows UTF-8 along with ASCII when using 1322; This is an experimental feature. This option allows UTF-8 along with ASCII when
1329; `suhosin.upload.disallow_binary` or `suhosin.upload.remove_binary`. 1323; using `suhosin.upload.disallow_binary` or `suhosin.upload.remove_binary`.
1330; 1324;
1331;suhosin.upload.allow_utf8 = Off 1325;suhosin.upload.allow_utf8 = Off
1332; 1326;
diff --git a/tests/filter/suhosin_upload_disallow_binary_utf8.phpt b/tests/filter/suhosin_upload_disallow_binary_utf8.phpt
index 557a8d5..b4627c7 100644
--- a/tests/filter/suhosin_upload_disallow_binary_utf8.phpt
+++ b/tests/filter/suhosin_upload_disallow_binary_utf8.phpt
@@ -11,7 +11,9 @@ suhosin.upload.allow_utf8=On
11max_file_uploads=40 11max_file_uploads=40
12suhosin.upload.max_uploads=40 12suhosin.upload.max_uploads=40
13--SKIPIF-- 13--SKIPIF--
14<?php include('skipif.inc'); ?> 14<?php include('skipif.inc');
15if (ini_get('suhosin.upload.allow_utf8') === FALSE) { die("skip feature not compiled in"); }
16?>
15--COOKIE-- 17--COOKIE--
16--GET-- 18--GET--
17--POST_RAW-- 19--POST_RAW--
diff --git a/tests/filter/suhosin_upload_disallow_binary_utf8fail.phpt b/tests/filter/suhosin_upload_disallow_binary_utf8fail.phpt
index 413d25a..0bf122b 100644
--- a/tests/filter/suhosin_upload_disallow_binary_utf8fail.phpt
+++ b/tests/filter/suhosin_upload_disallow_binary_utf8fail.phpt
@@ -11,7 +11,9 @@ suhosin.upload.allow_utf8=Off
11max_file_uploads=40 11max_file_uploads=40
12suhosin.upload.max_uploads=40 12suhosin.upload.max_uploads=40
13--SKIPIF-- 13--SKIPIF--
14<?php include('skipif.inc'); ?> 14<?php include('skipif.inc');
15if (ini_get('suhosin.upload.allow_utf8') === FALSE) { die("skip feature not compiled in"); }
16?>
15--COOKIE-- 17--COOKIE--
16--GET-- 18--GET--
17--POST_RAW-- 19--POST_RAW--
diff --git a/tests/filter/suhosin_upload_remove_binary_utf8.phpt b/tests/filter/suhosin_upload_remove_binary_utf8.phpt
index 6fbd240..1920dc5 100644
--- a/tests/filter/suhosin_upload_remove_binary_utf8.phpt
+++ b/tests/filter/suhosin_upload_remove_binary_utf8.phpt
@@ -12,7 +12,9 @@ suhosin.upload.allow_utf8=On
12max_file_uploads=40 12max_file_uploads=40
13suhosin.upload.max_uploads=40 13suhosin.upload.max_uploads=40
14--SKIPIF-- 14--SKIPIF--
15<?php include('skipif.inc'); ?> 15<?php include('skipif.inc');
16if (ini_get('suhosin.upload.allow_utf8') === FALSE) { die("skip feature not compiled in"); }
17?>
16--COOKIE-- 18--COOKIE--
17--GET-- 19--GET--
18--POST_RAW-- 20--POST_RAW--
diff --git a/tests/filter/suhosin_upload_remove_binary_utf8fail.phpt b/tests/filter/suhosin_upload_remove_binary_utf8fail.phpt
index 5c31115..56de404 100644
--- a/tests/filter/suhosin_upload_remove_binary_utf8fail.phpt
+++ b/tests/filter/suhosin_upload_remove_binary_utf8fail.phpt
@@ -12,7 +12,9 @@ suhosin.upload.allow_utf8=Off
12max_file_uploads=40 12max_file_uploads=40
13suhosin.upload.max_uploads=40 13suhosin.upload.max_uploads=40
14--SKIPIF-- 14--SKIPIF--
15<?php include('skipif.inc'); ?> 15<?php include('skipif.inc');
16if (ini_get('suhosin.upload.allow_utf8') === FALSE) { die("skip feature not compiled in"); }
17?>
16--COOKIE-- 18--COOKIE--
17--GET-- 19--GET--
18--POST_RAW-- 20--POST_RAW--
diff --git a/ufilter.c b/ufilter.c
index 1669e88..f3c3054 100644
--- a/ufilter.c
+++ b/ufilter.c
@@ -149,19 +149,23 @@ return_failure:
149} 149}
150/* }}} */ 150/* }}} */
151 151
152static inline int suhosin_validate_utf8_multibyte(const char* cp) 152#ifdef SUHOSIN_EXPERIMENTAL
153static inline int suhosin_validate_utf8_multibyte(const char* cp, size_t maxlen)
153{ 154{
155 if (maxlen < 2 || !(*cp & 0x80)) { return 0; }
154 if ((*cp & 0xe0) == 0xc0 && // 1st byte is 110xxxxx 156 if ((*cp & 0xe0) == 0xc0 && // 1st byte is 110xxxxx
155 (*(cp+1) & 0xc0) == 0x80 && // 2nd byte is 10xxxxxx 157 (*(cp+1) & 0xc0) == 0x80 && // 2nd byte is 10xxxxxx
156 (*cp & 0x1e)) { // overlong check 110[xxxx]x 10xxxxxx 158 (*cp & 0x1e)) { // overlong check 110[xxxx]x 10xxxxxx
157 return 2; 159 return 2;
158 } 160 }
161 if (maxlen < 3) { return 0; }
159 if ((*cp & 0xf0) == 0xe0 && // 1st byte is 1110xxxx 162 if ((*cp & 0xf0) == 0xe0 && // 1st byte is 1110xxxx
160 (*(cp+1) & 0xc0) == 0x80 && // 2nd byte is 10xxxxxx 163 (*(cp+1) & 0xc0) == 0x80 && // 2nd byte is 10xxxxxx
161 (*(cp+2) & 0xc0) == 0x80 && // 3rd byte is 10xxxxxx 164 (*(cp+2) & 0xc0) == 0x80 && // 3rd byte is 10xxxxxx
162 ((*cp & 0x0f) | (*(cp+1) & 0x20))) { // 1110[xxxx] 10[x]xxxxx 10xxxxxx 165 ((*cp & 0x0f) | (*(cp+1) & 0x20))) { // 1110[xxxx] 10[x]xxxxx 10xxxxxx
163 return 3; 166 return 3;
164 } 167 }
168 if (maxlen < 4) { return 0; }
165 if ((*cp & 0xf8) == 0xf0 && // 1st byte is 11110xxx 169 if ((*cp & 0xf8) == 0xf0 && // 1st byte is 11110xxx
166 (*(cp+1) & 0xc0) == 0x80 && // 2nd byte is 10xxxxxx 170 (*(cp+1) & 0xc0) == 0x80 && // 2nd byte is 10xxxxxx
167 (*(cp+2) & 0xc0) == 0x80 && // 3rd byte is 10xxxxxx 171 (*(cp+2) & 0xc0) == 0x80 && // 3rd byte is 10xxxxxx
@@ -171,6 +175,7 @@ static inline int suhosin_validate_utf8_multibyte(const char* cp)
171 } 175 }
172 return 0; 176 return 0;
173} 177}
178#endif
174 179
175int suhosin_rfc1867_filter(unsigned int event, void *event_data, void **extra TSRMLS_DC) 180int suhosin_rfc1867_filter(unsigned int event, void *event_data, void **extra TSRMLS_DC)
176{ 181{
@@ -236,14 +241,15 @@ int suhosin_rfc1867_filter(unsigned int event, void *event_data, void **extra TS
236 if (*cp >= 32 || isspace(*cp)) { 241 if (*cp >= 32 || isspace(*cp)) {
237 continue; 242 continue;
238 } 243 }
244#ifdef SUHOSIN_EXPERIMENTAL
239 if ((*cp & 0x80) && SUHOSIN_G(upload_allow_utf8)) { 245 if ((*cp & 0x80) && SUHOSIN_G(upload_allow_utf8)) {
240 SDEBUG("checking char %x", *cp); 246 SDEBUG("checking char %x", *cp);
241 if ((n = suhosin_validate_utf8_multibyte(cp))) { // valid UTF8 multibyte character 247 if ((n = suhosin_validate_utf8_multibyte(cp, cpend-cp))) { // valid UTF8 multibyte character
242 cp += n - 1; 248 cp += n - 1;
243 continue; 249 continue;
244 } 250 }
245 } 251 }
246 252#endif
247 suhosin_log(S_FILES, "uploaded file contains binary data - file dropped"); 253 suhosin_log(S_FILES, "uploaded file contains binary data - file dropped");
248 if (!SUHOSIN_G(simulation)) { 254 if (!SUHOSIN_G(simulation)) {
249 goto continue_with_failure; 255 goto continue_with_failure;
@@ -261,15 +267,17 @@ int suhosin_rfc1867_filter(unsigned int event, void *event_data, void **extra TS
261 for (i=0, j=0; i<mefd->length; i++) { 267 for (i=0, j=0; i<mefd->length; i++) {
262 if (mefd->data[i] >= 32 || isspace(mefd->data[i])) { 268 if (mefd->data[i] >= 32 || isspace(mefd->data[i])) {
263 mefd->data[j++] = mefd->data[i]; 269 mefd->data[j++] = mefd->data[i];
264 } else if (SUHOSIN_G(upload_allow_utf8) && mefd->data[i] & 0x80) { 270 }
265 n = suhosin_validate_utf8_multibyte(mefd->data + i); 271#ifdef SUHOSIN_EXPERIMENTAL
272 else if (SUHOSIN_G(upload_allow_utf8) && mefd->data[i] & 0x80) {
273 n = suhosin_validate_utf8_multibyte(mefd->data + i, mefd->length - i);
266 if (!n) { continue; } 274 if (!n) { continue; }
267 while (n) { 275 while (n--) {
268 mefd->data[j++] = mefd->data[i++]; 276 mefd->data[j++] = mefd->data[i++];
269 n--;
270 } 277 }
271 i--; 278 i--;
272 } 279 }
280#endif
273 } 281 }
274 mefd->data[j] = '\0'; 282 mefd->data[j] = '\0';
275 283