Added MULTIPART_UNMATCHED_BOUNDARY. Not very reliable, as it detects anything that looks like a boundary, which means any line that begins with -- but we don't think it's a boundary.

This commit is contained in:
ivanr 2007-08-10 09:59:57 +00:00
parent 70324713e4
commit c85773b343
3 changed files with 86 additions and 54 deletions

View File

@ -624,7 +624,7 @@ int multipart_process_chunk(modsec_rec *msr, const char *buf,
return -1; 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) { while(inleft > 0) {
char c = *inptr; char c = *inptr;
int process_buffer = 0; int process_buffer = 0;
@ -645,71 +645,79 @@ int multipart_process_chunk(modsec_rec *msr, const char *buf,
* or the end of our internal buffer * or the end of our internal buffer
*/ */
if ((c == 0x0a)||(msr->mpd->bufleft == 0)||(process_buffer)) { if ((c == 0x0a)||(msr->mpd->bufleft == 0)||(process_buffer)) {
int processed_as_boundary = 0;
*(msr->mpd->bufptr) = 0; *(msr->mpd->bufptr) = 0;
/* boundary preconditions: length of the line greater than /* Do we have something that looks like a boundary? */
* the length of the boundary + the first two characters if (msr->mpd->buf_contains_line
* are dashes "-" && (strlen(msr->mpd->buf) > 3)
*/ && (((*(msr->mpd->buf) == '-'))&&(*(msr->mpd->buf + 1) == '-')) )
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); /* Does it match our boundary? */
int is_final = 0; if ((strlen(msr->mpd->buf) >= strlen(msr->mpd->boundary) + 2)
&& (strncmp(msr->mpd->buf + 2, msr->mpd->boundary, strlen(msr->mpd->boundary)) == 0) )
/* Is this the final boundary? */
if ((*boundary_end == '-')&&(*(boundary_end + 1)== '-')) {
is_final = 1;
boundary_end += 2;
if (msr->mpd->is_complete != 0) {
*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') { char *boundary_end = msr->mpd->buf + 2 + strlen(msr->mpd->boundary);
msr->mpd->flag_lf_line = 1; 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) {
*error_msg = apr_psprintf(msr->mp,
"Multipart: Invalid boundary (final duplicate).");
return -1;
}
} }
if (multipart_process_boundary(msr, (is_final ? 1 : 0), error_msg) < 0) { /* 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) {
return -1;
}
if (is_final) {
msr->mpd->is_complete = 1;
}
processed_as_boundary = 1;
}
else {
/* error */
*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)
) {
*error_msg = apr_psprintf(msr->mp, "Multipart: Invalid boundary (quotes).");
return -1; return -1;
} }
if (is_final) { msr->mpd->flag_unmatched_boundary = 1;
msr->mpd->is_complete = 1;
}
}
else {
/* error */
*error_msg = apr_psprintf(msr->mp,
"Multipart: Invalid boundary: %s",
log_escape_nq(msr->mp, msr->mpd->buf));
return -1;
} }
} }
else {
if ( msr->mpd->buf_contains_line
&& (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)
) {
*error_msg = apr_psprintf(msr->mp, "Multipart: Invalid boundary (quotes).");
return -1;
}
/* Process as data if it was not a boundary. */
if (processed_as_boundary == 0) {
if (msr->mpd->mpp == NULL) { if (msr->mpd->mpp == NULL) {
msr->mpd->flag_data_before = 1; msr->mpd->flag_data_before = 1;
msr_log(msr, 4, "Multipart: Ignoring data before first boundary."); msr_log(msr, 4, "Multipart: Ignoring data before first boundary.");

View File

@ -103,6 +103,7 @@ struct multipart_data {
int flag_header_folding; int flag_header_folding;
int flag_boundary_quoted; int flag_boundary_quoted;
int flag_lf_line; int flag_lf_line;
int flag_unmatched_boundary;
}; };

View File

@ -1308,6 +1308,18 @@ static int var_multipart_strict_error_generate(modsec_rec *msr, msre_var *var, m
return var_simple_generate(var, vartab, mptmp, "0"); 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");
}
}
/* TIME */ /* TIME */
static int var_time_generate(modsec_rec *msr, msre_var *var, msre_rule *rule, static int var_time_generate(modsec_rec *msr, msre_var *var, msre_rule *rule,
@ -2306,6 +2318,17 @@ void msre_engine_register_default_variables(msre_engine *engine) {
PHASE_REQUEST_BODY 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
);
/* PATH_INFO */ /* PATH_INFO */
msre_engine_variable_register(engine, msre_engine_variable_register(engine,
"PATH_INFO", "PATH_INFO",