@@ -128,13 +128,46 @@ static int multipart_parse_content_disposition(modsec_rec *msr, char *c_d_value)
128128 while ((* p == '\t' ) || (* p == ' ' )) p ++ ;
129129 if (* p == '\0' ) return -6 ;
130130
131- /* Accept both quotes as some backends will accept them, but
132- * technically "'" is invalid and so flag_invalid_quoting is
133- * set so the user can deal with it in the rules if they so wish.
134- */
135-
136131 char quote = '\0' ;
137- if ((* p == '"' ) || (* p == '\'' )) {
132+ if (strcmp (name , "filename*" ) == 0 ) {
133+ /* filename*=charset'[optional-language]'filename */
134+ /* Read beyond the charset and the optional language*/
135+ const char * start_of_charset = p ;
136+ while ((* p != '\0' ) && (isalnum (* p ) || strchr (mime_charset_special , * p ) )) {
137+ p ++ ;
138+ }
139+ if ((* p != '\'' ) || (p == start_of_charset )) {
140+ return -16 ; // Must be at least one legit char before ' for start of language
141+ }
142+ p ++ ;
143+ while (isalnum (* p ) || * p == '-' ) p ++ ;
144+ if (* p != '\'' ) {
145+ return -17 ; // Single quote for end-of-language not found
146+ }
147+ p ++ ;
148+
149+ /* Now read what should be the actual filename */
150+ const char * start_of_filename = p ;
151+ while ((* p != '\0' ) && (* p != ';' )) {
152+ if (* p == '%' ) {
153+ if ((!isxdigit (* (p + 1 ))) || (!isxdigit (* (p + 2 )))) {
154+ return -18 ;
155+ }
156+ p += 3 ;
157+ }
158+ else if ((* p != '\0' ) && (isalnum (* p ) || strchr (mime_charset_special , * p ))) {
159+ p ++ ;
160+ }
161+ else {
162+ return -19 ;
163+ }
164+ }
165+ value = apr_pmemdup (msr -> mp , start_of_filename , p - start_of_filename );
166+ } else if ((* p == '"' ) || (* p == '\'' )) {
167+ /* Accept both quotes as some backends will accept them, but
168+ * technically "'" is invalid and so flag_invalid_quoting is
169+ * set so the user can deal with it in the rules if they so wish.
170+ */
138171 /* quoted */
139172 quote = * p ; // remember which quote character was used for the value
140173
@@ -228,52 +261,6 @@ static int multipart_parse_content_disposition(modsec_rec *msr, char *c_d_value)
228261 log_escape_nq (msr -> mp , value ));
229262 }
230263 else if (strcmp (name , "filename*" ) == 0 ) {
231- /* old restrictive code
232- if (strncasecmp(value, "UTF-8''", 7) && strncasecmp(value, "ISO-8859-1''", 12)) {
233- msr_log(msr, 4, "Multipart: filename* must contain encoding: %s", log_escape_nq(msr->mp, value));
234- msr->mpd->flag_error = 1;
235- return -16;
236- }
237- //msr_log(msr, 4, "Multipart: Warning: Content-Disposition filename* is obsolete (ignore it)");
238- */
239-
240- /* filename*=charset'[optional-language]'filename */
241- /* Read beyond the charset and the optional language*/
242- const char * start_of_charset = p ;
243- /*
244- if (strncasecmp(value, "UTF-8''", 7) == 0) p += 7;
245- else if (strncasecmp(value, "ISO-8859-1''", 12) == 0) p += 12;
246- */
247- while ((* p != '\0' ) && (isalnum (* p ) || strchr (mime_charset_special , * p ) )) {
248- p ++ ;
249- }
250- if ((* p != '\'' ) || (p == start_of_charset )) {
251- return -16 ; // Must be at least one legit char before ' for start of language
252- }
253- p ++ ;
254- while (isalnum (* p ) || * p == '-' ) p ++ ;
255- if (* p != '\'' ) {
256- return -17 ; // Single quote for end-of-language not found
257- }
258- p ++ ;
259-
260- /* Now read what should be the actual filename */
261- const char * start_of_filename = p ;
262- while ((* p != '\0' ) && (* p != ';' )) {
263- if (* p == '%' ) {
264- if ((!isxdigit (* (p + 1 ))) || (!isxdigit (* (p + 2 )))) {
265- return -18 ;
266- }
267- p += 3 ;
268- }
269- else if ((* p != '\0' ) && (isalnum (* p ) || strchr (mime_charset_special , * p ))) {
270- p ++ ;
271- }
272- else {
273- return -19 ;
274- }
275- }
276- value = apr_pmemdup (msr -> mp , start_of_filename , p - start_of_filename );
277264 if (filenameStar != NULL ) {
278265 msr_log (msr , 4 ,
279266 "Multipart: Warning: Duplicate Content-Disposition filename*: %s." , log_escape_nq (msr -> mp , value ));
0 commit comments