Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 24 additions & 25 deletions src/app-layer-ftp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand All @@ -351,18 +352,18 @@ 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;
input->len = 0;
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;
Expand All @@ -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;
Expand Down Expand Up @@ -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) {
Expand All @@ -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);
}
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
}
}
Expand Down
4 changes: 3 additions & 1 deletion src/app-layer-ftp.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_ {
Expand Down Expand Up @@ -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;
Expand Down