diff --git a/src/app-layer-ftp.c b/src/app-layer-ftp.c index 7f0accadc149..f96fcc362fd4 100644 --- a/src/app-layer-ftp.c +++ b/src/app-layer-ftp.c @@ -340,7 +340,8 @@ typedef struct FtpInput_ { int32_t orig_len; } FtpInput; -static AppLayerResult FTPGetLineForDirection(FtpState *state, FtpLineState *line, FtpInput *input) +static AppLayerResult FTPGetLineForDirection( + FtpState *state, FtpLineState *line, FtpInput *input, bool *current_line_truncated) { SCEnter(); @@ -351,8 +352,8 @@ static AppLayerResult FTPGetLineForDirection(FtpState *state, FtpLineState *line uint8_t *lf_idx = memchr(input->buf + input->consumed, 0x0a, input->len); if (lf_idx == NULL) { - if (!state->current_line_truncated && (uint32_t)input->len >= ftp_max_line_len) { - state->current_line_truncated = true; + if (!(*current_line_truncated) && (uint32_t)input->len >= ftp_max_line_len) { + *current_line_truncated = true; line->buf = input->buf; line->len = ftp_max_line_len; line->delim_len = 0; @@ -360,9 +361,9 @@ static AppLayerResult FTPGetLineForDirection(FtpState *state, FtpLineState *line SCReturnStruct(APP_LAYER_OK); } SCReturnStruct(APP_LAYER_INCOMPLETE(input->consumed, input->len + 1)); - } else if (state->current_line_truncated) { + } else if (*current_line_truncated) { // Whatever came in with first LF should also get discarded - state->current_line_truncated = false; + *current_line_truncated = false; line->len = 0; line->delim_len = 0; input->len = 0; @@ -372,26 +373,18 @@ static AppLayerResult FTPGetLineForDirection(FtpState *state, FtpLineState *line // e.g. input_len = 5077 // lf_idx = 5010 // max_line_len = 4096 - if (!state->current_line_truncated && (uint32_t)input->len >= ftp_max_line_len) { - state->current_line_truncated = true; - line->buf = input->buf; - line->len = ftp_max_line_len; - if (input->consumed >= 2 && input->buf[input->consumed - 2] == 0x0D) { - line->delim_len = 2; - line->len -= 2; - } else { - line->delim_len = 1; - line->len -= 1; - } - input->len = 0; - SCReturnStruct(APP_LAYER_OK); - } uint32_t o_consumed = input->consumed; input->consumed = lf_idx - input->buf + 1; line->len = input->consumed - o_consumed; input->len -= line->len; + line->lf_found = true; DEBUG_VALIDATE_BUG_ON((input->consumed + input->len) != input->orig_len); line->buf = input->buf + o_consumed; + if (line->len >= ftp_max_line_len) { + *current_line_truncated = true; + line->len = ftp_max_line_len; + SCReturnStruct(APP_LAYER_OK); + } if (input->consumed >= 2 && input->buf[input->consumed - 2] == 0x0D) { line->delim_len = 2; line->len -= 2; @@ -505,12 +498,12 @@ static AppLayerResult FTPParseRequest(Flow *f, void *ftp_state, AppLayerParserSt } FtpInput ftpi = { .buf = input, .len = input_len, .orig_len = input_len, .consumed = 0 }; - FtpLineState line = { .buf = NULL, .len = 0, .delim_len = 0 }; + FtpLineState line = { .buf = NULL, .len = 0, .delim_len = 0, .lf_found = false }; uint8_t direction = STREAM_TOSERVER; AppLayerResult res; while (1) { - res = FTPGetLineForDirection(state, &line, &ftpi); + res = FTPGetLineForDirection(state, &line, &ftpi, &state->current_line_truncated_ts); if (res.status == 1) { return res; } else if (res.status == -1) { @@ -531,8 +524,11 @@ static AppLayerResult FTPParseRequest(Flow *f, void *ftp_state, AppLayerParserSt tx->command_descriptor = cmd_descriptor; tx->request_length = CopyCommandLine(&tx->request, &line); - tx->request_truncated = state->current_line_truncated; + tx->request_truncated = state->current_line_truncated_ts; + if (line.lf_found) { + state->current_line_truncated_ts = false; + } if (tx->request_truncated) { AppLayerDecoderEventsSetEventRaw(&tx->tx_data.events, FtpEventRequestCommandTooLong); } @@ -695,12 +691,12 @@ static AppLayerResult FTPParseResponse(Flow *f, void *ftp_state, AppLayerParserS SCReturnStruct(APP_LAYER_OK); } FtpInput ftpi = { .buf = input, .len = input_len, .orig_len = input_len, .consumed = 0 }; - FtpLineState line = { .buf = NULL, .len = 0, .delim_len = 0 }; + FtpLineState line = { .buf = NULL, .len = 0, .delim_len = 0, .lf_found = false }; FTPTransaction *lasttx = TAILQ_FIRST(&state->tx_list); AppLayerResult res; while (1) { - res = FTPGetLineForDirection(state, &line, &ftpi); + res = FTPGetLineForDirection(state, &line, &ftpi, &state->current_line_truncated_tc); if (res.status == 1) { return res; } else if (res.status == -1) { @@ -771,11 +767,14 @@ static AppLayerResult FTPParseResponse(Flow *f, void *ftp_state, AppLayerParserS FTPString *response = FTPStringAlloc(); if (likely(response)) { response->len = CopyCommandLine(&response->str, &line); - response->truncated = state->current_line_truncated; + response->truncated = state->current_line_truncated_tc; if (response->truncated) { AppLayerDecoderEventsSetEventRaw( &tx->tx_data.events, FtpEventResponseCommandTooLong); } + if (line.lf_found) { + state->current_line_truncated_tc = false; + } TAILQ_INSERT_TAIL(&tx->response_list, response, next); } } diff --git a/src/app-layer-ftp.h b/src/app-layer-ftp.h index 39b53b6bf8bb..f79c5c9e7675 100644 --- a/src/app-layer-ftp.h +++ b/src/app-layer-ftp.h @@ -105,6 +105,7 @@ typedef struct FtpLineState_ { const uint8_t *buf; uint32_t len; uint8_t delim_len; + bool lf_found; } FtpLineState; typedef struct FTPString_ { @@ -148,7 +149,8 @@ typedef struct FtpState_ { TAILQ_HEAD(, FTPTransaction_) tx_list; /**< transaction list */ uint64_t tx_cnt; - bool current_line_truncated; + bool current_line_truncated_ts; + bool current_line_truncated_tc; FtpRequestCommand command; FtpRequestCommandArgOfs arg_offset;