Backport multipart changes to 2.1.x.

This commit is contained in:
ivanr
2007-08-10 15:17:32 +00:00
parent bd3845a62b
commit a9703a0559
4 changed files with 394 additions and 96 deletions

View File

@@ -172,38 +172,62 @@ static int multipart_parse_content_disposition(modsec_rec *msr, char *c_d_value)
*
*/
static int multipart_process_part_header(modsec_rec *msr, char **error_msg) {
int rc;
int i, rc;
if (error_msg == NULL) return -1;
*error_msg = NULL;
if ((msr->mpd->buf[0] == '\r')
&&(msr->mpd->buf[1] == '\n')
&&(msr->mpd->buf[2] == '\0'))
/* Check for nul bytes. */
for(i = 0; i < (MULTIPART_BUF_SIZE - msr->mpd->bufleft); i++) {
if (msr->mpd->buf[i] == '\0') {
*error_msg = apr_psprintf(msr->mp, "Multipart: Nul byte in part headers.");
return -1;
}
}
/* Is this an empty line? */
if ( ((msr->mpd->buf[0] == '\r')
&&(msr->mpd->buf[1] == '\n')
&&(msr->mpd->buf[2] == '\0') )
|| ((msr->mpd->buf[0] == '\n')
&&(msr->mpd->buf[1] == '\0') ) )
{
char *header_value;
/* empty line */
/* Empty line. */
if (msr->mpd->buf[0] == '\n') {
msr->mpd->flag_lf_line = 1;
}
header_value = (char *)apr_table_get(msr->mpd->mpp->headers, "Content-Disposition");
if (header_value == NULL) {
*error_msg = apr_psprintf(msr->mp, "Multipart: Part is missing the Content-Disposition header");
*error_msg = apr_psprintf(msr->mp, "Multipart: Part missing Content-Disposition header.");
return -1;
}
rc = multipart_parse_content_disposition(msr, header_value);
if (rc < 0) {
*error_msg = apr_psprintf(msr->mp, "Multipart: Invalid Content-Disposition header (%i): %s",
*error_msg = apr_psprintf(msr->mp, "Multipart: Invalid Content-Disposition header (%i): %s.",
rc, log_escape_nq(msr->mp, header_value));
return -1;
}
if (msr->mpd->mpp->name == NULL) {
*error_msg = apr_psprintf(msr->mp, "Multipart: Part name missing");
*error_msg = apr_psprintf(msr->mp, "Multipart: Content-Disposition header missing name field.");
return -1;
}
}
if (msr->mpd->mpp->filename != NULL) {
/* Some parsers use crude methods to extract the name and filename
* values from the C-D header. We need to check for the case where they
* don't understand and C-D we do.
*/
if (strstr(header_value, "filename=") == NULL) {
*error_msg = apr_psprintf(msr->mp, "Multipart: Invalid Content-Disposition header (filename).");
return -1;
}
msr->mpd->mpp->type = MULTIPART_FILE;
} else {
msr->mpd->mpp->type = MULTIPART_FORMDATA;
@@ -212,19 +236,20 @@ static int multipart_process_part_header(modsec_rec *msr, char **error_msg) {
msr->mpd->mpp_state = 1;
msr->mpd->mpp->last_header_name = NULL;
} else {
/* header line */
/* Header line. */
if ((msr->mpd->buf[0] == '\t')||(msr->mpd->buf[0] == ' ')) {
char *header_value, *new_value, *data;
/* header folding, add data to the header we are building */
msr->mpd->flag_header_folding = 1;
if (msr->mpd->mpp->last_header_name == NULL) {
/* we are not building a header at this moment */
*error_msg = apr_psprintf(msr->mp, "Multipart: invalid part header (invalid folding)");
*error_msg = apr_psprintf(msr->mp, "Multipart: Invalid part header (folding error).");
return -1;
}
/* locate the beginning of the data */
/* locate the beginning of data */
data = msr->mpd->buf;
while((*data == '\t')||(*data == ' ')) data++;
@@ -241,7 +266,7 @@ static int multipart_process_part_header(modsec_rec *msr, char **error_msg) {
log_escape(msr->mp, data));
if (strlen(new_value) > 4096) {
*error_msg = apr_psprintf(msr->mp, "Multpart: invalid part header (too long)");
*error_msg = apr_psprintf(msr->mp, "Multipart: Part header too long.");
return -1;
}
} else {
@@ -252,7 +277,7 @@ static int multipart_process_part_header(modsec_rec *msr, char **error_msg) {
data = msr->mpd->buf;
while((*data != ':')&&(*data != '\0')) data++;
if (*data == '\0') {
*error_msg = apr_psprintf(msr->mp, "Multipart: invalid part header (missing colon): %s",
*error_msg = apr_psprintf(msr->mp, "Multipart: Invalid part header (colon missing): %s.",
log_escape_nq(msr->mp, msr->mpd->buf));
return -1;
}
@@ -267,7 +292,7 @@ static int multipart_process_part_header(modsec_rec *msr, char **error_msg) {
/* error if the name already exists */
if (apr_table_get(msr->mpd->mpp->headers, header_name) != NULL) {
*error_msg = apr_psprintf(msr->mp, "Multipart: part header already exists: %s",
*error_msg = apr_psprintf(msr->mp, "Multipart: Duplicate part header: %s.",
log_escape_nq(msr->mp, header_name));
return -1;
}
@@ -288,22 +313,36 @@ static int multipart_process_part_header(modsec_rec *msr, char **error_msg) {
*
*/
static int multipart_process_part_data(modsec_rec *msr, char **error_msg) {
char *p = msr->mpd->buf + (MULTIPART_BUF_SIZE - msr->mpd->bufleft) - 2;
char *p = msr->mpd->buf + (MULTIPART_BUF_SIZE - msr->mpd->bufleft);
char localreserve[2] = { '\0', '\0' }; /* initialized to quiet warning */
int bytes_reserved = 0;
if (error_msg == NULL) return -1;
*error_msg = NULL;
/* preserve the last two bytes for later */
if (MULTIPART_BUF_SIZE - msr->mpd->bufleft >= 2) {
bytes_reserved = 1;
localreserve[0] = *p;
localreserve[1] = *(p + 1);
msr->mpd->bufleft += 2;
*p = 0;
}
/* Preserve some bytes for later. */
if ( ((MULTIPART_BUF_SIZE - msr->mpd->bufleft) >= 1)
&& (*(p - 1) == '\n') )
{
if ( ((MULTIPART_BUF_SIZE - msr->mpd->bufleft) >= 2)
&& (*(p - 2) == '\r') )
{
/* Two bytes. */
bytes_reserved = 2;
localreserve[0] = *(p - 1);
localreserve[1] = *(p - 2);
msr->mpd->bufleft += 2;
*(p - 2) = 0;
} else {
/* Only one byte. */
bytes_reserved = 1;
localreserve[0] = *(p - 1);
localreserve[1] = 0;
msr->mpd->bufleft += 1;
*(p - 1) = 0;
}
}
/* add data to the part we are building */
if (msr->mpd->mpp->type == MULTIPART_FILE) {
@@ -318,8 +357,6 @@ static int multipart_process_part_data(modsec_rec *msr, char **error_msg) {
if (msr->upload_extract_files) {
/* first create a temporary file if we don't have it already */
if (msr->mpd->mpp->tmp_file_fd == 0) {
// char *filename = multipart_construct_filename(msr);
/* construct temporary file name */
msr->mpd->mpp->tmp_file_name = apr_psprintf(msr->mp, "%s/%s-%s-file-XXXXXX",
msr->txcfg->tmp_dir, current_filetime(msr->mp), msr->txid);
@@ -337,14 +374,15 @@ static int multipart_process_part_data(modsec_rec *msr, char **error_msg) {
}
/* write the reserve first */
if (msr->mpd->reserve[0] == 1) {
if (write(msr->mpd->mpp->tmp_file_fd, &msr->mpd->reserve[1], 2) != 2) {
if (msr->mpd->reserve[0] != 0) {
if (write(msr->mpd->mpp->tmp_file_fd, &msr->mpd->reserve[1], msr->mpd->reserve[0]) != msr->mpd->reserve[0]) {
*error_msg = apr_psprintf(msr->mp, "Multipart: writing to \"%s\" failed",
log_escape(msr->mp, msr->mpd->mpp->tmp_file_name));
return -1;
}
msr->mpd->mpp->tmp_file_size += 2;
msr->mpd->mpp->length += 2;
msr->mpd->mpp->tmp_file_size += msr->mpd->reserve[0];
msr->mpd->mpp->length += msr->mpd->reserve[0];
}
/* write data to the file */
@@ -360,11 +398,8 @@ static int multipart_process_part_data(modsec_rec *msr, char **error_msg) {
msr->mpd->mpp->length += (MULTIPART_BUF_SIZE - msr->mpd->bufleft);
} else {
/* just keep track of the file size */
if (msr->mpd->reserve[0] == 1) {
msr->mpd->mpp->tmp_file_size += 2;
}
msr->mpd->mpp->tmp_file_size += (MULTIPART_BUF_SIZE - msr->mpd->bufleft);
msr->mpd->mpp->length += (MULTIPART_BUF_SIZE - msr->mpd->bufleft);
msr->mpd->mpp->tmp_file_size += (MULTIPART_BUF_SIZE - msr->mpd->bufleft) + msr->mpd->reserve[0];
msr->mpd->mpp->length += (MULTIPART_BUF_SIZE - msr->mpd->bufleft) + msr->mpd->reserve[0];
}
}
else if (msr->mpd->mpp->type == MULTIPART_FORMDATA) {
@@ -376,12 +411,13 @@ static int multipart_process_part_data(modsec_rec *msr, char **error_msg) {
if (msr->mpd->mpp->length == 0) {
msr->mpd->mpp->offset = msr->mpd->buf_offset;
}
if (msr->mpd->reserve[0] == 1) {
value_part->data = apr_palloc(msr->mp, (MULTIPART_BUF_SIZE - msr->mpd->bufleft) + 2);
memcpy(value_part->data, &(msr->mpd->reserve[1]), 2);
memcpy(value_part->data + 2, msr->mpd->buf, (MULTIPART_BUF_SIZE - msr->mpd->bufleft));
value_part->length = (MULTIPART_BUF_SIZE - msr->mpd->bufleft) + 2;
if (msr->mpd->reserve[0] != 0) {
value_part->data = apr_palloc(msr->mp, (MULTIPART_BUF_SIZE - msr->mpd->bufleft) + msr->mpd->reserve[0]);
memcpy(value_part->data, &(msr->mpd->reserve[1]), msr->mpd->reserve[0]);
memcpy(value_part->data + msr->mpd->reserve[0], msr->mpd->buf, (MULTIPART_BUF_SIZE - msr->mpd->bufleft));
value_part->length = (MULTIPART_BUF_SIZE - msr->mpd->bufleft) + msr->mpd->reserve[0];
msr->mpd->mpp->length += value_part->length;
} else {
value_part->length = (MULTIPART_BUF_SIZE - msr->mpd->bufleft);
@@ -403,14 +439,14 @@ static int multipart_process_part_data(modsec_rec *msr, char **error_msg) {
* context so that they don't get lost
*/
if (bytes_reserved) {
msr->mpd->reserve[0] = 1;
msr->mpd->reserve[0] = bytes_reserved;
msr->mpd->reserve[1] = localreserve[0];
msr->mpd->reserve[2] = localreserve[1];
msr->mpd->buf_offset += 2;
msr->mpd->buf_offset += bytes_reserved;
}
else {
msr->mpd->buf_offset -= msr->mpd->reserve[0];
msr->mpd->reserve[0] = 0;
msr->mpd->buf_offset -= 2;
}
return 1;
@@ -510,6 +546,12 @@ int multipart_init(modsec_rec *msr, char **error_msg) {
msr->mpd = (multipart_data *)apr_pcalloc(msr->mp, sizeof(multipart_data));
if (msr->mpd == NULL) return -1;
msr->mpd->parts = apr_array_make(msr->mp, 10, sizeof(multipart_part *));
msr->mpd->bufleft = MULTIPART_BUF_SIZE;
msr->mpd->bufptr = msr->mpd->buf;
msr->mpd->buf_contains_line = 1;
msr->mpd->mpp = NULL;
if (msr->request_content_type == NULL) {
*error_msg = apr_psprintf(msr->mp, "Multipart: Content-Type header not available.");
return -1;
@@ -517,19 +559,48 @@ int multipart_init(modsec_rec *msr, char **error_msg) {
msr->mpd->boundary = strstr(msr->request_content_type, "boundary=");
if ((msr->mpd->boundary != NULL)&&(*(msr->mpd->boundary + 9) != 0)) {
msr->mpd->boundary = msr->mpd->boundary + 9;
char *b = msr->mpd->boundary + 9;
int len = strlen(b);
/* Is the boundary quoted? */
if ((len >= 2)&&(*b == '"')&&(*(b + len - 1) == '"')) {
/* Quoted. */
msr->mpd->boundary = apr_pstrndup(msr->mp, b + 1, len - 2);
msr->mpd->flag_boundary_quoted = 1;
if (strstr(msr->mpd->boundary, "\"") != NULL) {
*error_msg = apr_psprintf(msr->mp, "Invalid boundary in C-T (quote).");
return -1;
}
} else {
/* Not quoted. */
/* Test for partial quoting. */
if ( (*b == '"')
|| ((len >= 2)&&(*(b + len - 1) == '"')) )
{
*error_msg = apr_psprintf(msr->mp, "Invalid boundary in C-T (quote).");
return -1;
}
msr->mpd->boundary = apr_pstrdup(msr->mp, b);
msr->mpd->flag_boundary_quoted = 0;
}
msr_log(msr, 9, "Multipart: Boundary%s: %s",
(msr->mpd->flag_boundary_quoted ? " (quoted)" : ""),
log_escape_nq(msr->mp, msr->mpd->boundary));
if (strlen(msr->mpd->boundary) == 0) {
*error_msg = apr_psprintf(msr->mp, "Multipart boundary in C-T empty.");
return -1;
}
}
else {
*error_msg = apr_psprintf(msr->mp, "Multipart Boundary not found or invalid.");
*error_msg = apr_psprintf(msr->mp, "Multipart boundary in C-T not found or invalid.");
return -1;
}
msr->mpd->parts = apr_array_make(msr->mp, 10, sizeof(multipart_part *));
msr->mpd->bufleft = MULTIPART_BUF_SIZE;
msr->mpd->bufptr = msr->mpd->buf;
msr->mpd->buf_contains_line = 1;
msr->mpd->mpp = NULL;
return 1;
}
@@ -540,7 +611,7 @@ int multipart_complete(modsec_rec *msr, char **error_log) {
if (msr->mpd == NULL) return 1;
if ((msr->mpd->seen_data != 0)&&(msr->mpd->is_complete == 0)) {
*error_log = apr_psprintf(msr->mp, "Multipart: final boundary missing");
*error_log = apr_psprintf(msr->mp, "Multipart: Final boundary missing.");
return -1;
}
@@ -564,17 +635,19 @@ int multipart_process_chunk(modsec_rec *msr, const char *buf,
if (msr->mpd->seen_data == 0) msr->mpd->seen_data = 1;
if (msr->mpd->is_complete) {
msr->mpd->flag_data_before = 1;
msr_log(msr, 4, "Multipart: Ignoring data after last boundary (received %i bytes)", size);
return 1;
}
if (msr->mpd->bufleft == 0) {
msr->mpd->flag_error = 1;
*error_msg = apr_psprintf(msr->mp,
"Multipart: Internal error in process_chunk: no space left in the buffer");
return -1;
}
/* here we loop through the data available, byte by byte */
/* here we loop through the available data, one byte at a time */
while(inleft > 0) {
char c = *inptr;
int process_buffer = 0;
@@ -595,47 +668,85 @@ int multipart_process_chunk(modsec_rec *msr, const char *buf,
* or the end of our internal buffer
*/
if ((c == 0x0a)||(msr->mpd->bufleft == 0)||(process_buffer)) {
int processed_as_boundary = 0;
*(msr->mpd->bufptr) = 0;
/* boundary preconditions: length of the line greater than
* the length of the boundary + the first two characters
* are dashes "-"
*/
if ( msr->mpd->buf_contains_line
&& (strlen(msr->mpd->buf) > strlen(msr->mpd->boundary) + 2)
&& (((*(msr->mpd->buf) == '-'))&&(*(msr->mpd->buf + 1) == '-'))
&& (strncmp(msr->mpd->buf + 2, msr->mpd->boundary, strlen(msr->mpd->boundary)) == 0) ) {
char *boundary_end = msr->mpd->buf + 2 + strlen(msr->mpd->boundary);
if ( (*boundary_end == '\r')
&&(*(boundary_end + 1) == '\n')
&&(*(boundary_end + 2) == '\0')
) {
/* simple boundary */
if (multipart_process_boundary(msr, 0, error_msg) < 0) return -1;
}
else
if ( (*boundary_end == '-')
&&(*(boundary_end + 1) == '-')
&&(*(boundary_end + 2) == '\r')
&&(*(boundary_end + 3) == '\n')
&&(*(boundary_end + 4) == '\0')
) {
/* final boundary */
msr->mpd->is_complete = 1;
if (multipart_process_boundary(msr, 1, error_msg) < 0) return -1;
}
else {
/* error */
*error_msg = apr_psprintf(msr->mp,
"Multipart: Invalid boundary detected: %s",
log_escape_nq(msr->mp, msr->mpd->buf));
return -1;
/* Do we have something that looks like a boundary? */
if (msr->mpd->buf_contains_line
&& (strlen(msr->mpd->buf) > 3)
&& (((*(msr->mpd->buf) == '-'))&&(*(msr->mpd->buf + 1) == '-')) )
{
/* Does it match our boundary? */
if ((strlen(msr->mpd->buf) >= strlen(msr->mpd->boundary) + 2)
&& (strncmp(msr->mpd->buf + 2, msr->mpd->boundary, strlen(msr->mpd->boundary)) == 0) )
{
char *boundary_end = msr->mpd->buf + 2 + strlen(msr->mpd->boundary);
int is_final = 0;
/* Is this the final boundary? */
if ((*boundary_end == '-')&&(*(boundary_end + 1)== '-')) {
is_final = 1;
boundary_end += 2;
if (msr->mpd->is_complete != 0) {
msr->mpd->flag_error = 1;
*error_msg = apr_psprintf(msr->mp,
"Multipart: Invalid boundary (final duplicate).");
return -1;
}
}
/* Allow for CRLF and LF line endings. */
if ( ( (*boundary_end == '\r')
&& (*(boundary_end + 1) == '\n')
&& (*(boundary_end + 2) == '\0') )
|| ( (*boundary_end == '\n')
&& (*(boundary_end + 1) == '\0') ) )
{
if (*boundary_end == '\n') {
msr->mpd->flag_lf_line = 1;
}
if (multipart_process_boundary(msr, (is_final ? 1 : 0), error_msg) < 0) {
msr->mpd->flag_error = 1;
return -1;
}
if (is_final) {
msr->mpd->is_complete = 1;
}
processed_as_boundary = 1;
}
else {
/* error */
msr->mpd->flag_error = 1;
*error_msg = apr_psprintf(msr->mp,
"Multipart: Invalid boundary: %s",
log_escape_nq(msr->mp, msr->mpd->buf));
return -1;
}
} else {
if ( (msr->mpd->flag_boundary_quoted)
&& (strlen(msr->mpd->buf) >= strlen(msr->mpd->boundary) + 3)
&& (((*(msr->mpd->buf) == '-'))&&(*(msr->mpd->buf + 1) == '-'))
&& (*(msr->mpd->buf + 2) == '"')
&& (strncmp(msr->mpd->buf + 3, msr->mpd->boundary, strlen(msr->mpd->boundary)) == 0)
) {
msr->mpd->flag_error = 1;
*error_msg = apr_psprintf(msr->mp, "Multipart: Invalid boundary (quotes).");
return -1;
}
msr->mpd->flag_unmatched_boundary = 1;
}
}
else {
/* Process as data if it was not a boundary. */
if (processed_as_boundary == 0) {
if (msr->mpd->mpp == NULL) {
msr->mpd->flag_data_before = 1;
msr_log(msr, 4, "Multipart: Ignoring data before first boundary.");
} else {
if (msr->mpd->mpp_state == 0) {
@@ -643,14 +754,22 @@ int multipart_process_chunk(modsec_rec *msr, const char *buf,
/* part header lines must be shorter than
* MULTIPART_BUF_SIZE bytes
*/
msr->mpd->flag_error = 1;
*error_msg = apr_psprintf(msr->mp,
"Multipart: Part header line over %i bytes long",
MULTIPART_BUF_SIZE);
return -1;
}
if (multipart_process_part_header(msr, error_msg) < 0) return -1;
if (multipart_process_part_header(msr, error_msg) < 0) {
msr->mpd->flag_error = 1;
return -1;
}
} else {
if (multipart_process_part_data(msr, error_msg) < 0) return -1;
if (multipart_process_part_data(msr, error_msg) < 0) {
msr->mpd->flag_error = 1;
return -1;
}
}
}
}
@@ -670,6 +789,7 @@ int multipart_process_chunk(modsec_rec *msr, const char *buf,
}
if ((msr->mpd->is_complete)&&(inleft != 0)) {
msr->mpd->flag_data_after = 1;
msr_log(msr, 4, "Multipart: Ignoring data after last boundary (%i bytes left)", inleft);
return 1;
}

View File

@@ -97,6 +97,14 @@ struct multipart_data {
int seen_data;
int is_complete;
int flag_error;
int flag_data_before;
int flag_data_after;
int flag_header_folding;
int flag_boundary_quoted;
int flag_lf_line;
int flag_unmatched_boundary;
};

View File

@@ -240,7 +240,7 @@ apr_status_t modsecurity_request_body_store(modsec_rec *msr,
if (multipart_process_chunk(msr, data, length, &my_error_msg) < 0) {
msr->msc_reqbody_error = 1;
msr->msc_reqbody_error_msg = my_error_msg;
msr_log(msr, 4, "%s", my_error_msg);
msr_log(msr, 1, "Request body processor error: %s", my_error_msg);
}
}
#ifdef WITH_LIBXML2
@@ -249,7 +249,7 @@ apr_status_t modsecurity_request_body_store(modsec_rec *msr,
if (xml_process_chunk(msr, data, length, &my_error_msg) < 0) {
msr->msc_reqbody_error = 1;
msr->msc_reqbody_error_msg = my_error_msg;
msr_log(msr, 4, "%s", my_error_msg);
msr_log(msr, 1, "Request body processor error: %s", my_error_msg);
}
}
#endif

View File

@@ -1651,6 +1651,99 @@ static int var_webappid_generate(modsec_rec *msr, msre_var *var, msre_rule *rule
return var_simple_generate(var, vartab, mptmp, value);
}
/* MULTIPART_BOUNDARY_QUOTED */
static int var_multipart_boundary_quoted_generate(modsec_rec *msr, msre_var *var, msre_rule *rule,
apr_table_t *vartab, apr_pool_t *mptmp)
{
if ((msr->mpd != NULL)&&(msr->mpd->flag_boundary_quoted != 0)) {
return var_simple_generate(var, vartab, mptmp, "1");
} else {
return var_simple_generate(var, vartab, mptmp, "0");
}
}
/* MULTIPART_DATA_AFTER */
static int var_multipart_data_after_generate(modsec_rec *msr, msre_var *var, msre_rule *rule,
apr_table_t *vartab, apr_pool_t *mptmp)
{
if ((msr->mpd != NULL)&&(msr->mpd->flag_data_after != 0)) {
return var_simple_generate(var, vartab, mptmp, "1");
} else {
return var_simple_generate(var, vartab, mptmp, "0");
}
}
/* MULTIPART_DATA_BEFORE */
static int var_multipart_data_before_generate(modsec_rec *msr, msre_var *var, msre_rule *rule,
apr_table_t *vartab, apr_pool_t *mptmp)
{
if ((msr->mpd != NULL)&&(msr->mpd->flag_data_before != 0)) {
return var_simple_generate(var, vartab, mptmp, "1");
} else {
return var_simple_generate(var, vartab, mptmp, "0");
}
}
/* MULTIPART_HEADER_FOLDING */
static int var_multipart_header_folding_generate(modsec_rec *msr, msre_var *var, msre_rule *rule,
apr_table_t *vartab, apr_pool_t *mptmp)
{
if ((msr->mpd != NULL)&&(msr->mpd->flag_header_folding != 0)) {
return var_simple_generate(var, vartab, mptmp, "1");
} else {
return var_simple_generate(var, vartab, mptmp, "0");
}
}
/* MULTIPART_LF_LINE */
static int var_multipart_lf_line_generate(modsec_rec *msr, msre_var *var, msre_rule *rule,
apr_table_t *vartab, apr_pool_t *mptmp)
{
if ((msr->mpd != NULL)&&(msr->mpd->flag_lf_line != 0)) {
return var_simple_generate(var, vartab, mptmp, "1");
} else {
return var_simple_generate(var, vartab, mptmp, "0");
}
}
/* MULTIPART_STRICT_ERROR */
static int var_multipart_strict_error_generate(modsec_rec *msr, msre_var *var, msre_rule *rule,
apr_table_t *vartab, apr_pool_t *mptmp)
{
if (msr->mpd != NULL) {
/* Respond positive if at least one of the multipart flags is raised. */
if ( (msr->mpd->flag_error)
||(msr->mpd->flag_boundary_quoted != 0)
||(msr->mpd->flag_data_before != 0)
||(msr->mpd->flag_data_after != 0)
||(msr->mpd->flag_header_folding != 0)
||(msr->mpd->flag_lf_line != 0)
) {
return var_simple_generate(var, vartab, mptmp, "1");
}
}
return var_simple_generate(var, vartab, mptmp, "0");
}
/* MULTIPART_UNMATCHED_BOUNDARY */
static int var_multipart_unmatched_boundary_generate(modsec_rec *msr, msre_var *var, msre_rule *rule,
apr_table_t *vartab, apr_pool_t *mptmp)
{
if ((msr->mpd != NULL)&&(msr->mpd->flag_unmatched_boundary != 0)) {
return var_simple_generate(var, vartab, mptmp, "1");
} else {
return var_simple_generate(var, vartab, mptmp, "0");
}
}
/* ---------------------------------------------- */
/**
@@ -2431,4 +2524,81 @@ void msre_engine_register_default_variables(msre_engine *engine) {
VAR_DONT_CACHE,
PHASE_RESPONSE_HEADERS
);
/* MULTIPART_BOUNDARY_QUOTED */
msre_engine_variable_register(engine,
"MULTIPART_BOUNDARY_QUOTED",
VAR_SIMPLE,
0, 0,
NULL,
var_multipart_boundary_quoted_generate,
VAR_CACHE,
PHASE_REQUEST_BODY
);
/* MULTIPART_DATA_AFTER */
msre_engine_variable_register(engine,
"MULTIPART_DATA_AFTER",
VAR_SIMPLE,
0, 0,
NULL,
var_multipart_data_after_generate,
VAR_CACHE,
PHASE_REQUEST_BODY
);
/* MULTIPART_DATA_BEFORE */
msre_engine_variable_register(engine,
"MULTIPART_DATA_BEFORE",
VAR_SIMPLE,
0, 0,
NULL,
var_multipart_data_before_generate,
VAR_CACHE,
PHASE_REQUEST_BODY
);
/* MULTIPART_HEADER_FOLDING */
msre_engine_variable_register(engine,
"MULTIPART_HEADER_FOLDING",
VAR_SIMPLE,
0, 0,
NULL,
var_multipart_header_folding_generate,
VAR_CACHE,
PHASE_REQUEST_BODY
);
/* MULTIPART_LF_LINE */
msre_engine_variable_register(engine,
"MULTIPART_LF_LINE",
VAR_SIMPLE,
0, 0,
NULL,
var_multipart_lf_line_generate,
VAR_CACHE,
PHASE_REQUEST_BODY
);
/* MULTIPART_STRICT_ERROR */
msre_engine_variable_register(engine,
"MULTIPART_STRICT_ERROR",
VAR_SIMPLE,
0, 0,
NULL,
var_multipart_strict_error_generate,
VAR_CACHE,
PHASE_REQUEST_BODY
);
/* MULTIPART_UNMATCHED_BOUNDARY */
msre_engine_variable_register(engine,
"MULTIPART_UNMATCHED_BOUNDARY",
VAR_SIMPLE,
0, 0,
NULL,
var_multipart_unmatched_boundary_generate,
VAR_CACHE,
PHASE_REQUEST_BODY
);
}