Skip to content

Commit

Permalink
Handle "filename*" field in MP header
Browse files Browse the repository at this point in the history
  • Loading branch information
airween committed Aug 25, 2024
1 parent fd0e042 commit cd4905b
Showing 1 changed file with 51 additions and 3 deletions.
54 changes: 51 additions & 3 deletions apache2/msc_multipart.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
#include "msc_util.h"
#include "msc_parsers.h"

static const char* mime_charset_special = "!#$%&+-^_`{}~";
static const char* attr_char_special = "!#$&+-.^_`~";

void validate_quotes(modsec_rec *msr, char *data, char quote) {
assert(msr != NULL);
int i, len;
Expand Down Expand Up @@ -85,6 +88,7 @@ static int multipart_parse_content_disposition(modsec_rec *msr, char *c_d_value)
assert(msr != NULL);
assert(c_d_value != NULL);
char *p = NULL, *t = NULL;
char *filenameStar = NULL;

/* accept only what we understand */
if (strncmp(c_d_value, "form-data", 9) != 0) {
Expand Down Expand Up @@ -130,7 +134,41 @@ static int multipart_parse_content_disposition(modsec_rec *msr, char *c_d_value)
*/

char quote = '\0';
if ((*p == '"') || (*p == '\'')) {
if (name == "filename*") {
/* filename*=charset'[optional-language]'filename */
/* Read beyond the charset and the optional language*/
const char* start_of_charset = p;
while ((*p != '\0') && (isalnum(*p) || (strchr(mime_charset_special, *p)))) {
p++;
}
if ((*p != '\'') || (p == start_of_charset)) {
return -16; // Must be at least one legit char before ' for start of language
}
p++;
while ((*p != '\0') && (*p != '\'')) {
p++;
}
if (*p != '\'') {
return -17; // Single quote for end-of-language not found
}
p++;

/* Now read what should be the actual filename */
const char* start_of_filename = p;
while ((*p != '\0') && (*p != ';')) {
if (*p == '%') {
if ((*(p+1) == '\0') || (!isxdigit(*(p+1))) || (!isxdigit(*(p+2)))) {
return -18;
}
p += 3;
} else if (isalnum(*p) || strchr(attr_char_special, *p)) {
p++;
} else {
return -19;
}
}
value = apr_pmemdup(msr->mp, start_of_filename, p - start_of_filename);
} else if ((*p == '"') || (*p == '\'')) {
/* quoted */
quote = *p; // remember which quote character was used for the value

Expand Down Expand Up @@ -205,8 +243,7 @@ static int multipart_parse_content_disposition(modsec_rec *msr, char *c_d_value)
log_escape_nq(msr->mp, value));
}
}
else
if (strcmp(name, "filename") == 0) {
else if (strcmp(name, "filename") == 0) {

validate_quotes(msr, value, quote);

Expand All @@ -223,6 +260,17 @@ static int multipart_parse_content_disposition(modsec_rec *msr, char *c_d_value)
msr_log(msr, 9, "Multipart: Content-Disposition filename: %s",
log_escape_nq(msr->mp, value));
}
} else if (strcmp(name, "filename*") == 0) {
if (filenameStar != NULL && strlen(filenameStar) != 0) {
msr_log(msr, 4,
"Multipart: Warning: Duplicate Content-Disposition filename*: %s.", log_escape_nq(msr->mp, value));
return -20;
}
filenameStar = apr_pstrdup(msr->mp, value);
if (msr->txcfg->debuglog_level >= 9) {
msr_log(msr, 9, "Multipart: Content-Disposition filename*: %s.",
log_escape_nq(msr->mp, value));
}
}
else return -11;

Expand Down

0 comments on commit cd4905b

Please sign in to comment.