Go to the documentation of this file.
69 #define FTP_MPM mpm_default_matcher
71 static MpmCtx *ftp_mpm_ctx = NULL;
134 static void FTPParseMemcap(
void)
136 const char *conf_val;
139 if ((
ConfGet(
"app-layer.protocols.ftp.memcap", &conf_val)) == 1)
143 "from conf file - %s. Killing engine",
157 static void FTPIncrMemuse(uint64_t size)
163 static void FTPDecrMemuse(uint64_t size)
187 static int FTPCheckMemcap(uint64_t size)
195 static void *FTPMalloc(
size_t size)
199 if (FTPCheckMemcap((uint32_t)size) == 0)
207 FTPIncrMemuse((uint64_t)size);
212 static void *FTPCalloc(
size_t n,
size_t size)
214 if (FTPCheckMemcap((uint32_t)(n * size)) == 0)
222 FTPIncrMemuse((uint64_t)(n * size));
226 static void *FTPRealloc(
void *ptr,
size_t orig_size,
size_t size)
230 if (FTPCheckMemcap((uint32_t)(size - orig_size)) == 0)
237 if (size > orig_size) {
238 FTPIncrMemuse(size - orig_size);
240 FTPDecrMemuse(orig_size - size);
246 static void FTPFree(
void *ptr,
size_t size)
250 FTPDecrMemuse((uint64_t)size);
261 FTPFree(
str->str,
str->len);
267 static void *FTPLocalStorageAlloc(
void)
276 if (td->
pmq == NULL) {
289 static void FTPLocalStorageFree(
void *ptr)
293 if (td->
pmq != NULL) {
321 SCLogDebug(
"new transaction %p (state tx cnt %"PRIu64
")", tx, state->
tx_cnt);
343 FTPFree(tx,
sizeof(*tx));
355 FTPFree(line_state->
db, line_state->
db_len);
356 line_state->
db = NULL;
365 if (lf_idx == NULL) {
374 if (line_state->
db == NULL) {
381 ptmp = FTPRealloc(line_state->
db, line_state->
db_len,
384 FTPFree(line_state->
db, line_state->
db_len);
385 line_state->
db = NULL;
389 line_state->
db = ptmp;
391 memcpy(line_state->
db + line_state->
db_len,
404 ptmp = FTPRealloc(line_state->
db, line_state->
db_len,
405 (line_state->
db_len + (lf_idx + 1 - state->
input)));
407 FTPFree(line_state->
db, line_state->
db_len);
408 line_state->
db = NULL;
412 line_state->
db = ptmp;
414 memcpy(line_state->
db + line_state->
db_len,
418 if (line_state->
db_len > 1 &&
419 line_state->
db[line_state->
db_len - 2] == 0x0D) {
434 if (state->
input != lf_idx &&
435 *(lf_idx - 1) == 0x0D) {
444 state->
input = (lf_idx + 1);
451 static int FTPGetLine(
FtpState *state)
461 return FTPGetLineForDirection(state, &state->
line_state[0]);
463 return FTPGetLineForDirection(state, &state->
line_state[1]);
477 const uint8_t *input, uint32_t input_len,
486 td->
pmq, input, input_len);
492 *cmd_descriptor = NULL;
506 static void FtpTransferCmdFree(
void *data)
511 if (
cmd->file_name) {
512 FTPFree(
cmd->file_name,
cmd->file_len + 1);
517 static uint32_t CopyCommandLine(uint8_t **dest,
const uint8_t *
src, uint32_t
length)
520 uint8_t *where = FTPCalloc(
length + 1,
sizeof(
char));
527 while (
length && isspace((
unsigned char) where[
length - 1])) {
549 static AppLayerResult FTPParseRequest(
Flow *f,
void *ftp_state,
551 const uint8_t *input, uint32_t input_len,
552 void *local_data,
const uint8_t
flags)
564 }
else if (input == NULL || input_len == 0) {
568 state->
input = input;
574 while (FTPGetLine(state) >= 0) {
577 if (!FTPParseRequestCommand(thread_data,
640 data->
DFree = FtpTransferCmdFree;
646 data->
file_name = FTPCalloc(file_name_len + 1,
sizeof(
char));
648 FtpTransferCmdFree(data);
659 FtpTransferCmdFree(data);
663 SCLogDebug(
"Expectation created [direction: %s, dynamic port %"PRIu16
"].",
664 state->
active ?
"to server" :
"to client",
682 static int FTPParsePassiveResponse(
Flow *f,
FtpState *state,
const uint8_t *input, uint32_t input_len)
684 uint16_t dyn_port = rs_ftp_pasv_response(input, input_len);
688 SCLogDebug(
"FTP passive mode (v4): dynamic port %"PRIu16
"", dyn_port);
697 static int FTPParsePassiveResponseV6(
Flow *f,
FtpState *state,
const uint8_t *input, uint32_t input_len)
699 uint16_t dyn_port = rs_ftp_epsv_response(input, input_len);
703 SCLogDebug(
"FTP passive mode (v6): dynamic port %"PRIu16
"", dyn_port);
720 static inline bool FTPIsPPR(
const uint8_t *input, uint32_t input_len)
722 return input_len >= 4 && isdigit(input[0]) && input[0] ==
'1' &&
723 isdigit(input[1]) && isdigit(input[2]) && isspace(input[3]);
736 const uint8_t *input, uint32_t input_len,
737 void *local_data,
const uint8_t
flags)
744 state->
input = input;
750 while (FTPGetLine(state) >= 0) {
753 tx = FTPTransactionCreate(state);
782 SCLogDebug(
"FTP active mode (v6): dynamic port %"PRIu16
"", dyn_port);
794 SCLogDebug(
"FTP active mode (v4): dynamic port %"PRIu16
"", dyn_port);
834 static uint64_t ftp_state_memuse = 0;
835 static uint64_t ftp_state_memcnt = 0;
838 static void *FTPStateAlloc(
void *orig_state,
AppProto proto_orig)
840 void *s = FTPCalloc(1,
sizeof(
FtpState));
856 static void FTPStateFree(
void *s)
871 SCLogDebug(
"[%s] state %p id %"PRIu64
", Freeing %d bytes at %p",
875 FTPTransactionFree(tx);
905 SCLogDebug(
"NULL state object; no transactions available");
922 SCLogDebug(
"Returning OLDEST tx %p id %"PRIu64, lasttx, lasttx->
tx_id);
926 static void *FTPGetTx(
void *state, uint64_t tx_id)
932 if (ftp_state->
curr_tx == NULL)
938 if (tx->
tx_id == tx_id)
952 static AppLayerTxData *FTPGetTxData(
void *vtx)
958 static void FTPStateTransactionFree(
void *state, uint64_t tx_id)
963 if (tx_id < tx->tx_id)
965 else if (tx_id > tx->
tx_id)
971 FTPTransactionFree(tx);
976 static uint64_t FTPGetTxCnt(
void *state)
983 SCLogDebug(
"returning state %p %"PRIu64, state, cnt);
987 static int FTPGetAlstateProgress(
void *vtx, uint8_t direction)
1004 static int FTPRegisterPatternsForProtocolDetection(
void)
1049 const uint8_t *input, uint32_t input_len,
1050 void *local_data,
int direction)
1056 if (ftpdata_state->
files == NULL) {
1063 if (ftpdata_state->
files == NULL) {
1074 switch (data->
cmd) {
1088 0ULL, (uint8_t *) ftpdata_state->
file_name,
1090 input, input_len,
flags) != 0) {
1096 if (input_len != 0) {
1100 SCLogDebug(
"FileAppendData() - file no longer being extracted");
1102 }
else if (ret < 0) {
1103 SCLogDebug(
"FileAppendData() failed: %d", ret);
1118 if (input_len && eof_flag) {
1130 static AppLayerResult FTPDataParseRequest(
Flow *f,
void *ftp_state,
1132 const uint8_t *input, uint32_t input_len,
1133 void *local_data,
const uint8_t
flags)
1135 return FTPDataParse(f, ftp_state, pstate, input, input_len,
1139 static AppLayerResult FTPDataParseResponse(
Flow *f,
void *ftp_state,
1141 const uint8_t *input, uint32_t input_len,
1142 void *local_data,
const uint8_t
flags)
1144 return FTPDataParse(f, ftp_state, pstate, input, input_len,
1150 static uint64_t ftpdata_state_memuse = 0;
1151 static uint64_t ftpdata_state_memcnt = 0;
1154 static void *FTPDataStateAlloc(
void *orig_state,
AppProto proto_orig)
1165 ftpdata_state_memcnt++;
1172 static void FTPDataStateFree(
void *s)
1188 ftpdata_state_memcnt--;
1207 static AppLayerTxData *FTPDataGetTxData(
void *vtx)
1213 static void FTPDataStateTransactionFree(
void *state, uint64_t tx_id)
1218 static void *FTPDataGetTx(
void *state, uint64_t tx_id)
1224 static uint64_t FTPDataGetTxCnt(
void *state)
1230 static int FTPDataGetAlstateProgress(
void *tx, uint8_t direction)
1233 return ftpdata_state->
state;
1236 static FileContainer *FTPDataStateGetFiles(
void *state, uint8_t direction)
1240 if (direction != ftpdata_state->
direction)
1246 static void FTPSetMpmState(
void)
1249 if (
unlikely(ftp_mpm_ctx == NULL)) {
1252 memset(ftp_mpm_ctx, 0,
sizeof(
MpmCtx));
1258 if (
cmd->command_length == 0)
1262 (uint8_t *)
cmd->command_name,
1263 cmd->command_length,
1272 static void FTPFreeMpmState(
void)
1274 if (ftp_mpm_ctx != NULL) {
1283 const char *proto_name =
"ftp";
1284 const char *proto_data_name =
"ftp-data";
1289 if (FTPRegisterPatternsForProtocolDetection() < 0 )
1305 FTPGetTxDetectState, FTPSetTxDetectState);
1311 FTPLocalStorageFree);
1321 FTPDataParseRequest);
1323 FTPDataParseResponse);
1328 FTPDataGetTxDetectState, FTPDataSetTxDetectState);
1343 sbcfg.
Malloc = FTPMalloc;
1344 sbcfg.
Calloc = FTPCalloc;
1346 sbcfg.
Free = FTPFree;
1350 SCLogInfo(
"Parsed disabled for %s protocol. Protocol detection"
1351 "still on.", proto_name);
1365 SCLogDebug(
"ftp_state_memcnt %"PRIu64
", ftp_state_memuse %"PRIu64
"",
1366 ftp_state_memcnt, ftp_state_memuse);
1391 if (!buffer || *buffer ==
'\0') {
1395 char *c = strchr(buffer,
'\n');
1396 return c == NULL ?
len : c - buffer + 1;
1408 jb_set_string_from_bytes(jb,
"filename", ftp_state->
file_name, ftp_state->
file_len);
1434 static int FTPParserTest01(
void)
1437 uint8_t ftpbuf[] =
"PORT 192,168,1,1,0,80\r\n";
1438 uint32_t ftplen =
sizeof(ftpbuf) - 1;
1442 memset(&f, 0,
sizeof(f));
1443 memset(&ssn, 0,
sizeof(ssn));
1446 f.
proto = IPPROTO_TCP;
1465 static int FTPParserTest03(
void)
1468 uint8_t ftpbuf1[] =
"POR";
1469 uint32_t ftplen1 =
sizeof(ftpbuf1) - 1;
1470 uint8_t ftpbuf2[] =
"T 192,168,1";
1471 uint32_t ftplen2 =
sizeof(ftpbuf2) - 1;
1472 uint8_t ftpbuf3[] =
"1,1,10,20\r\n";
1473 uint32_t ftplen3 =
sizeof(ftpbuf3) - 1;
1477 memset(&f, 0,
sizeof(f));
1478 memset(&ssn, 0,
sizeof(ssn));
1481 f.
proto = IPPROTO_TCP;
1510 static int FTPParserTest06(
void)
1513 uint8_t ftpbuf1[] =
"PORT";
1514 uint32_t ftplen1 =
sizeof(ftpbuf1) - 1;
1518 memset(&f, 0,
sizeof(f));
1519 memset(&ssn, 0,
sizeof(ssn));
1522 f.
proto = IPPROTO_TCP;
1544 static int FTPParserTest07(
void)
1547 uint8_t ftpbuf1[] =
"PO";
1548 uint32_t ftplen1 =
sizeof(ftpbuf1) - 1;
1549 uint8_t ftpbuf2[] =
"RT\r\n";
1550 uint32_t ftplen2 =
sizeof(ftpbuf2) - 1;
1554 memset(&f, 0,
sizeof(f));
1555 memset(&ssn, 0,
sizeof(ssn));
1558 f.
proto = IPPROTO_TCP;
1584 static int FTPParserTest10(
void)
1587 uint8_t ftpbuf1[] =
"PORT 1,2,3,4,5,6\r\n";
1588 uint32_t ftplen1 =
sizeof(ftpbuf1) - 1;
1592 memset(&f, 0,
sizeof(f));
1593 memset(&ssn, 0,
sizeof(ssn));
1596 f.
proto = IPPROTO_TCP;
1602 for (u = 0; u < ftplen1; u++) {
1625 static int FTPParserTest11(
void)
1628 uint8_t ftpbuf1[] =
"PORT 192,168,1,1,0,80\r\n";
1629 uint8_t ftpbuf2[] =
"RETR\r\n";
1630 uint8_t ftpbuf3[] =
"227 OK\r\n";
1635 memset(&f, 0,
sizeof(f));
1636 memset(&ssn, 0,
sizeof(ssn));
1639 f.
proto = IPPROTO_TCP;
1646 sizeof(ftpbuf1) - 1);
1653 sizeof(ftpbuf3) - 1);
1658 sizeof(ftpbuf2) - 1);
1672 static int FTPParserTest12(
void)
1675 uint8_t ftpbuf1[] =
"PORT 192,168,1,1,0,80\r\n";
1676 uint8_t ftpbuf2[] =
"STOR\r\n";
1677 uint8_t ftpbuf3[] =
"227 OK\r\n";
1682 memset(&f, 0,
sizeof(f));
1683 memset(&ssn, 0,
sizeof(ssn));
1686 f.
proto = IPPROTO_TCP;
1693 sizeof(ftpbuf1) - 1);
1700 sizeof(ftpbuf3) - 1);
1705 sizeof(ftpbuf2) - 1);
void MpmInitThreadCtx(MpmThreadCtx *mpm_thread_ctx, uint16_t matcher)
uint8_t current_line_lf_seen
void AppLayerParserRegisterGetStateProgressFunc(uint8_t ipproto, AppProto alproto, int(*StateGetProgress)(void *alstate, uint8_t direction))
const FtpCommand * command_descriptor
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
void *(* Malloc)(size_t size)
int AppLayerProtoDetectPMRegisterPatternCI(uint8_t ipproto, AppProto alproto, const char *pattern, uint16_t depth, uint16_t offset, uint8_t direction)
Registers a case-insensitive pattern for protocol detection.
void AppLayerParserRegisterLocalStorageFunc(uint8_t ipproto, AppProto alproto, void *(*LocalStorageAlloc)(void), void(*LocalStorageFree)(void *))
#define SC_ATOMIC_INIT(name)
wrapper for initializing an atomic variable.
const FtpCommand FtpCommands[FTP_COMMAND_MAX+1]
FileContainer * FileContainerAlloc(void)
allocate a FileContainer
void *(* Calloc)(size_t n, size_t size)
struct FtpState_ FtpState
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
structure for storing potential rule matches
int ParseSizeStringU64(const char *size, uint64_t *res)
struct HtpBodyChunk_ * next
void MpmInitCtx(MpmCtx *mpm_ctx, uint16_t matcher)
FtpRequestCommand command
int AppLayerParserConfParserEnabled(const char *ipproto, const char *alproto_name)
check if a parser is enabled in the config Returns enabled always if: were running unittests
#define STREAMING_BUFFER_CONFIG_INITIALIZER
#define SC_ATOMIC_ADD(name, val)
add a value to our atomic variable
void AppLayerParserRegisterStateProgressCompletionStatus(AppProto alproto, const int ts, const int tc)
void AppLayerParserRegisterParserAcceptableDataDirection(uint8_t ipproto, AppProto alproto, uint8_t direction)
FtpLineState line_state[2]
void AppLayerParserRegisterTxFreeFunc(uint8_t ipproto, AppProto alproto, void(*StateTransactionFree)(void *, uint64_t))
#define TAILQ_FOREACH(var, head, field)
FtpRequestCommand command
uint64_t FTPMemuseGlobalCounter(void)
void AppLayerParserThreadCtxFree(AppLayerParserThreadCtx *tctx)
Destroys the app layer parser thread context obtained using AppLayerParserThreadCtxAlloc().
FtpRequestCommand command
void AppLayerParserRegisterDetectStateFuncs(uint8_t ipproto, AppProto alproto, DetectEngineState *(*GetTxDetectState)(void *tx), int(*SetTxDetectState)(void *tx, DetectEngineState *))
#define SCMUTEX_INITIALIZER
const char * command_name
#define TAILQ_INSERT_TAIL(head, elm, field)
int AppLayerExpectationGetDataId(void)
#define APP_LAYER_PARSER_EOF_TS
int FileAppendData(FileContainer *ffc, const uint8_t *data, uint32_t data_len)
Store/handle a chunk of file data in the File structure The last file in the FileContainer will be us...
SC_ATOMIC_DECLARE(uint64_t, ftp_memuse)
void FTPParserCleanup(void)
Free memory allocated for global FTP parser state.
@ FTPDATA_STATE_IN_PROGRESS
int ConfGet(const char *name, const char **vptr)
Retrieve the value of a configuration node.
int AppLayerParserStateIssetFlag(AppLayerParserState *pstate, uint8_t flag)
#define TAILQ_REMOVE(head, elm, field)
#define JB_SET_STRING(jb, key, val)
#define TAILQ_FIRST(head)
#define PASS
Pass the test.
uint16_t FileFlowToFlags(const Flow *flow, uint8_t direction)
#define SCMutexUnlock(mut)
AppLayerParserThreadCtx * alp_tctx
void AppLayerParserRegisterGetFilesFunc(uint8_t ipproto, AppProto alproto, FileContainer *(*StateGetFiles)(void *, uint8_t))
void AppLayerParserRegisterStateFuncs(uint8_t ipproto, AppProto alproto, void *(*StateAlloc)(void *, AppProto), void(*StateFree)(void *))
void PmqReset(PrefilterRuleStore *)
Reset a Pmq for reusage. Meant to be called after a single search.
#define SC_ATOMIC_SUB(name, val)
sub a value from our atomic variable
void FTPParserRegisterTests(void)
void RegisterFTPParsers(void)
void AppLayerParserRegisterProtocolUnittests(uint8_t ipproto, AppProto alproto, void(*RegisterUnittests)(void))
int AppLayerExpectationCreate(Flow *f, int direction, Port src, Port dst, AppProto alproto, void *data)
void StreamTcpFreeConfig(char quiet)
#define APP_LAYER_PARSER_EOF_TC
uint64_t ftp_config_memcap
void AppLayerRegisterExpectationProto(uint8_t proto, AppProto alproto)
int(* Prepare)(struct MpmCtx_ *)
int FileOpenFileWithId(FileContainer *ffc, const StreamingBufferConfig *sbcfg, uint32_t track_id, const uint8_t *name, uint16_t name_len, const uint8_t *data, uint32_t data_len, uint16_t flags)
Open a new File.
#define SCReturnPtr(x, type)
Data structures and function prototypes for keeping state for the detection engine.
void AppLayerProtoDetectRegisterProtocol(AppProto alproto, const char *alproto_name)
Registers a protocol for protocol detection phase.
struct FtpDataState_ FtpDataState
uint64_t FTPMemcapGlobalCounter(void)
uint32_t(* Search)(const struct MpmCtx_ *, struct MpmThreadCtx_ *, PrefilterRuleStore *, const uint8_t *, uint32_t)
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
int AppLayerParserRegisterParser(uint8_t ipproto, AppProto alproto, uint8_t direction, AppLayerParserFPtr Parser)
Register app layer parser for the protocol.
void DetectEngineStateFree(DetectEngineState *state)
Frees a DetectEngineState object.
#define SCRealloc(ptr, sz)
AppLayerParserThreadCtx * AppLayerParserThreadCtxAlloc(void)
Gets a new app layer protocol's parser thread context.
void AppLayerParserRegisterGetTx(uint8_t ipproto, AppProto alproto, void *(StateGetTx)(void *alstate, uint64_t tx_id))
const uint8_t * current_line
void AppLayerRequestProtocolTLSUpgrade(Flow *f)
request applayer to wrap up this protocol and rerun protocol detection with expectation of TLS....
#define SCReturnStruct(x)
#define FAIL_IF(expr)
Fail a test if expression evaluates to false.
int AppLayerParserParse(ThreadVars *tv, AppLayerParserThreadCtx *alp_tctx, Flow *f, AppProto alproto, uint8_t flags, const uint8_t *input, uint32_t input_len)
uint32_t current_line_len
DetectEngineState * de_state
#define TAILQ_NEXT(elm, field)
void PmqFree(PrefilterRuleStore *)
Cleanup and free a Pmq.
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
void AppLayerParserRegisterTxDataFunc(uint8_t ipproto, AppProto alproto, AppLayerTxData *(*GetTxData)(void *tx))
void FTPAtExitPrintStats(void)
void(* DestroyCtx)(struct MpmCtx_ *)
int PmqSetup(PrefilterRuleStore *)
Setup a pmq.
void(* Free)(void *ptr, size_t size)
void EveFTPDataAddMetadata(const Flow *f, JsonBuilder *jb)
void StreamTcpInitConfig(char)
To initialize the stream global configuration data.
DetectEngineState * de_state
void * FlowGetStorageById(Flow *f, int id)
MpmTableElmt mpm_table[MPM_TABLE_SIZE]
void AppLayerParserRegisterGetTxCnt(uint8_t ipproto, AppProto alproto, uint64_t(*StateGetTxCnt)(void *alstate))
void(* DestroyThreadCtx)(struct MpmCtx_ *, struct MpmThreadCtx_ *)
void FileContainerFree(FileContainer *ffc)
Free a FileContainer.
#define SC_ATOMIC_GET(name)
Get the value from the atomic variable.
uint16_t JsonGetNextLineFromBuffer(const char *buffer, const uint16_t len)
struct FTPThreadCtx_ FTPThreadCtx
AppProto alproto
application level protocol
void FlowFreeStorageById(Flow *f, int id)
uint8_t current_line_delimiter_len
int MpmAddPatternCI(struct MpmCtx_ *mpm_ctx, uint8_t *pat, uint16_t patlen, uint16_t offset, uint16_t depth, uint32_t pid, SigIntId sid, uint8_t flags)
#define SCMemcmp(a, b, c)
int AppLayerProtoDetectConfProtoDetectionEnabled(const char *ipproto, const char *alproto)
Given a protocol name, checks if proto detection is enabled in the conf file.
int FileCloseFile(FileContainer *ffc, const uint8_t *data, uint32_t data_len, uint16_t flags)
Close a File.
MpmThreadCtx * ftp_mpm_thread_ctx
void *(* Realloc)(void *ptr, size_t orig_size, size_t size)