20
20
#include "msc_util.h"
21
21
#include "msc_parsers.h"
22
22
23
+ static const char * mime_charset_special = "!#$%&+-^_`{}~" ;
24
+ static const char * attr_char_special = "!#$&+-.^_`~" ;
25
+
23
26
void validate_quotes (modsec_rec * msr , char * data , char quote ) {
24
27
assert (msr != NULL );
25
28
int i , len ;
@@ -85,6 +88,7 @@ static int multipart_parse_content_disposition(modsec_rec *msr, char *c_d_value)
85
88
assert (msr != NULL );
86
89
assert (c_d_value != NULL );
87
90
char * p = NULL , * t = NULL ;
91
+ char * filenameStar = NULL ;
88
92
89
93
/* accept only what we understand */
90
94
if (strncmp (c_d_value , "form-data" , 9 ) != 0 ) {
@@ -130,7 +134,41 @@ static int multipart_parse_content_disposition(modsec_rec *msr, char *c_d_value)
130
134
*/
131
135
132
136
char quote = '\0' ;
133
- if ((* p == '"' ) || (* p == '\'' )) {
137
+ if (name == "filename*" ) {
138
+ /* filename*=charset'[optional-language]'filename */
139
+ /* Read beyond the charset and the optional language*/
140
+ const char * start_of_charset = p ;
141
+ while ((* p != '\0' ) && (isalnum (* p ) || (strchr (mime_charset_special , * p )))) {
142
+ p ++ ;
143
+ }
144
+ if ((* p != '\'' ) || (p == start_of_charset )) {
145
+ return -16 ; // Must be at least one legit char before ' for start of language
146
+ }
147
+ p ++ ;
148
+ while ((* p != '\0' ) && (* p != '\'' )) {
149
+ p ++ ;
150
+ }
151
+ if (* p != '\'' ) {
152
+ return -17 ; // Single quote for end-of-language not found
153
+ }
154
+ p ++ ;
155
+
156
+ /* Now read what should be the actual filename */
157
+ const char * start_of_filename = p ;
158
+ while ((* p != '\0' ) && (* p != ';' )) {
159
+ if (* p == '%' ) {
160
+ if ((* (p + 1 ) == '\0' ) || (!isxdigit (* (p + 1 ))) || (!isxdigit (* (p + 2 )))) {
161
+ return -18 ;
162
+ }
163
+ p += 3 ;
164
+ } else if (isalnum (* p ) || strchr (attr_char_special , * p )) {
165
+ p ++ ;
166
+ } else {
167
+ return -19 ;
168
+ }
169
+ }
170
+ value = apr_pmemdup (msr -> mp , start_of_filename , p - start_of_filename );
171
+ } else if ((* p == '"' ) || (* p == '\'' )) {
134
172
/* quoted */
135
173
quote = * p ; // remember which quote character was used for the value
136
174
@@ -205,8 +243,7 @@ static int multipart_parse_content_disposition(modsec_rec *msr, char *c_d_value)
205
243
log_escape_nq (msr -> mp , value ));
206
244
}
207
245
}
208
- else
209
- if (strcmp (name , "filename" ) == 0 ) {
246
+ else if (strcmp (name , "filename" ) == 0 ) {
210
247
211
248
validate_quotes (msr , value , quote );
212
249
@@ -223,6 +260,17 @@ static int multipart_parse_content_disposition(modsec_rec *msr, char *c_d_value)
223
260
msr_log (msr , 9 , "Multipart: Content-Disposition filename: %s" ,
224
261
log_escape_nq (msr -> mp , value ));
225
262
}
263
+ } else if (strcmp (name , "filename*" ) == 0 ) {
264
+ if (filenameStar != NULL && strlen (filenameStar ) != 0 ) {
265
+ msr_log (msr , 4 ,
266
+ "Multipart: Warning: Duplicate Content-Disposition filename*: %s." , log_escape_nq (msr -> mp , value ));
267
+ return -20 ;
268
+ }
269
+ filenameStar = apr_pstrdup (msr -> mp , value );
270
+ if (msr -> txcfg -> debuglog_level >= 9 ) {
271
+ msr_log (msr , 9 , "Multipart: Content-Disposition filename*: %s." ,
272
+ log_escape_nq (msr -> mp , value ));
273
+ }
226
274
}
227
275
else return -11 ;
228
276
0 commit comments