suricata
app-layer-ftp.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2020 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author Pablo Rincon Crespo <pablo.rincon.crespo@gmail.com>
22  * \author Eric Leblond <eric@regit.org>
23  * \author Jeff Lucovsky <jeff@lucovsky.org>
24  *
25  * App Layer Parser for FTP
26  */
27 
28 #include "suricata-common.h"
29 #include "debug.h"
30 #include "decode.h"
31 #include "threads.h"
32 
33 #include "util-print.h"
34 #include "util-pool.h"
35 
36 #include "flow-util.h"
37 #include "flow-storage.h"
38 
39 #include "detect-engine-state.h"
40 
41 #include "stream-tcp-private.h"
42 #include "stream-tcp-reassemble.h"
43 #include "stream-tcp.h"
44 #include "stream.h"
45 
46 #include "app-layer.h"
47 #include "app-layer-protos.h"
48 #include "app-layer-parser.h"
49 #include "app-layer-ftp.h"
50 #include "app-layer-expectation.h"
51 
52 #include "util-spm.h"
53 #include "util-mpm.h"
54 #include "util-unittest.h"
55 #include "util-debug.h"
56 #include "util-memcmp.h"
57 #include "util-memrchr.h"
58 #include "util-mem.h"
59 #include "util-misc.h"
60 
61 #include "output-json.h"
62 #include "rust.h"
63 
64 typedef struct FTPThreadCtx_ {
68 
69 #define FTP_MPM mpm_default_matcher
70 
71 static MpmCtx *ftp_mpm_ctx = NULL;
72 
74  /* Parsed and handled */
75  { FTP_COMMAND_PORT, "PORT", 4},
76  { FTP_COMMAND_EPRT, "EPRT", 4},
77  { FTP_COMMAND_AUTH_TLS, "AUTH TLS", 8},
78  { FTP_COMMAND_PASV, "PASV", 4},
79  { FTP_COMMAND_RETR, "RETR", 4},
80  { FTP_COMMAND_EPSV, "EPSV", 4},
81  { FTP_COMMAND_STOR, "STOR", 4},
82 
83  /* Parsed, but not handled */
84  { FTP_COMMAND_ABOR, "ABOR", 4},
85  { FTP_COMMAND_ACCT, "ACCT", 4},
86  { FTP_COMMAND_ALLO, "ALLO", 4},
87  { FTP_COMMAND_APPE, "APPE", 4},
88  { FTP_COMMAND_CDUP, "CDUP", 4},
89  { FTP_COMMAND_CHMOD, "CHMOD", 5},
90  { FTP_COMMAND_CWD, "CWD", 3},
91  { FTP_COMMAND_DELE, "DELE", 4},
92  { FTP_COMMAND_HELP, "HELP", 4},
93  { FTP_COMMAND_IDLE, "IDLE", 4},
94  { FTP_COMMAND_LIST, "LIST", 4},
95  { FTP_COMMAND_MAIL, "MAIL", 4},
96  { FTP_COMMAND_MDTM, "MDTM", 4},
97  { FTP_COMMAND_MKD, "MKD", 3},
98  { FTP_COMMAND_MLFL, "MLFL", 4},
99  { FTP_COMMAND_MODE, "MODE", 4},
100  { FTP_COMMAND_MRCP, "MRCP", 4},
101  { FTP_COMMAND_MRSQ, "MRSQ", 4},
102  { FTP_COMMAND_MSAM, "MSAM", 4},
103  { FTP_COMMAND_MSND, "MSND", 4},
104  { FTP_COMMAND_MSOM, "MSOM", 4},
105  { FTP_COMMAND_NLST, "NLST", 4},
106  { FTP_COMMAND_NOOP, "NOOP", 4},
107  { FTP_COMMAND_PASS, "PASS", 4},
108  { FTP_COMMAND_PWD, "PWD", 3},
109  { FTP_COMMAND_QUIT, "QUIT", 4},
110  { FTP_COMMAND_REIN, "REIN", 4},
111  { FTP_COMMAND_REST, "REST", 4},
112  { FTP_COMMAND_RMD, "RMD", 3},
113  { FTP_COMMAND_RNFR, "RNFR", 4},
114  { FTP_COMMAND_RNTO, "RNTO", 4},
115  { FTP_COMMAND_SITE, "SITE", 4},
116  { FTP_COMMAND_SIZE, "SIZE", 4},
117  { FTP_COMMAND_SMNT, "SMNT", 4},
118  { FTP_COMMAND_STAT, "STAT", 4},
119  { FTP_COMMAND_STOU, "STOU", 4},
120  { FTP_COMMAND_STRU, "STRU", 4},
121  { FTP_COMMAND_SYST, "SYST", 4},
122  { FTP_COMMAND_TYPE, "TYPE", 4},
123  { FTP_COMMAND_UMASK, "UMASK", 5},
124  { FTP_COMMAND_USER, "USER", 4},
125  { FTP_COMMAND_UNKNOWN, NULL, 0}
126 };
127 uint64_t ftp_config_memcap = 0;
128 
129 SC_ATOMIC_DECLARE(uint64_t, ftp_memuse);
130 SC_ATOMIC_DECLARE(uint64_t, ftp_memcap);
131 
132 static FTPTransaction *FTPGetOldestTx(FtpState *);
133 
134 static void FTPParseMemcap(void)
135 {
136  const char *conf_val;
137 
138  /** set config values for memcap, prealloc and hash_size */
139  if ((ConfGet("app-layer.protocols.ftp.memcap", &conf_val)) == 1)
140  {
141  if (ParseSizeStringU64(conf_val, &ftp_config_memcap) < 0) {
142  SCLogError(SC_ERR_SIZE_PARSE, "Error parsing ftp.memcap "
143  "from conf file - %s. Killing engine",
144  conf_val);
145  exit(EXIT_FAILURE);
146  }
147  SCLogInfo("FTP memcap: %"PRIu64, ftp_config_memcap);
148  } else {
149  /* default to unlimited */
150  ftp_config_memcap = 0;
151  }
152 
153  SC_ATOMIC_INIT(ftp_memuse);
154  SC_ATOMIC_INIT(ftp_memcap);
155 }
156 
157 static void FTPIncrMemuse(uint64_t size)
158 {
159  (void) SC_ATOMIC_ADD(ftp_memuse, size);
160  return;
161 }
162 
163 static void FTPDecrMemuse(uint64_t size)
164 {
165  (void) SC_ATOMIC_SUB(ftp_memuse, size);
166  return;
167 }
168 
170 {
171  uint64_t tmpval = SC_ATOMIC_GET(ftp_memuse);
172  return tmpval;
173 }
174 
176 {
177  uint64_t tmpval = SC_ATOMIC_GET(ftp_memcap);
178  return tmpval;
179 }
180 
181 /**
182  * \brief Check if alloc'ing "size" would mean we're over memcap
183  *
184  * \retval 1 if in bounds
185  * \retval 0 if not in bounds
186  */
187 static int FTPCheckMemcap(uint64_t size)
188 {
189  if (ftp_config_memcap == 0 || size + SC_ATOMIC_GET(ftp_memuse) <= ftp_config_memcap)
190  return 1;
191  (void) SC_ATOMIC_ADD(ftp_memcap, 1);
192  return 0;
193 }
194 
195 static void *FTPMalloc(size_t size)
196 {
197  void *ptr = NULL;
198 
199  if (FTPCheckMemcap((uint32_t)size) == 0)
200  return NULL;
201 
202  ptr = SCMalloc(size);
203 
204  if (unlikely(ptr == NULL))
205  return NULL;
206 
207  FTPIncrMemuse((uint64_t)size);
208 
209  return ptr;
210 }
211 
212 static void *FTPCalloc(size_t n, size_t size)
213 {
214  void *ptr = NULL;
215 
216  if (FTPCheckMemcap((uint32_t)(n * size)) == 0)
217  return NULL;
218 
219  ptr = SCCalloc(n, size);
220 
221  if (unlikely(ptr == NULL))
222  return NULL;
223 
224  FTPIncrMemuse((uint64_t)(n * size));
225 
226  return ptr;
227 }
228 
229 static void *FTPRealloc(void *ptr, size_t orig_size, size_t size)
230 {
231  void *rptr = NULL;
232 
233  if (FTPCheckMemcap((uint32_t)(size - orig_size)) == 0)
234  return NULL;
235 
236  rptr = SCRealloc(ptr, size);
237  if (rptr == NULL)
238  return NULL;
239 
240  if (size > orig_size) {
241  FTPIncrMemuse(size - orig_size);
242  } else {
243  FTPDecrMemuse(orig_size - size);
244  }
245 
246  return rptr;
247 }
248 
249 static void FTPFree(void *ptr, size_t size)
250 {
251  SCFree(ptr);
252 
253  FTPDecrMemuse((uint64_t)size);
254 }
255 
256 static FTPString *FTPStringAlloc(void)
257 {
258  return FTPCalloc(1, sizeof(FTPString));
259 }
260 
261 static void FTPStringFree(FTPString *str)
262 {
263  if (str->str) {
264  FTPFree(str->str, str->len);
265  }
266 
267  FTPFree(str, sizeof(FTPString));
268 }
269 
270 static void *FTPLocalStorageAlloc(void)
271 {
272  /* needed by the mpm */
273  FTPThreadCtx *td = SCCalloc(1, sizeof(*td));
274  if (td == NULL) {
275  exit(EXIT_FAILURE);
276  }
277 
278  td->pmq = SCCalloc(1, sizeof(*td->pmq));
279  if (td->pmq == NULL) {
280  exit(EXIT_FAILURE);
281  }
282  PmqSetup(td->pmq);
283 
284  td->ftp_mpm_thread_ctx = SCCalloc(1, sizeof(MpmThreadCtx));
285  if (unlikely(td->ftp_mpm_thread_ctx == NULL)) {
286  exit(EXIT_FAILURE);
287  }
289  return td;
290 }
291 
292 static void FTPLocalStorageFree(void *ptr)
293 {
294  FTPThreadCtx *td = ptr;
295  if (td != NULL) {
296  if (td->pmq != NULL) {
297  PmqFree(td->pmq);
298  SCFree(td->pmq);
299  }
300 
301  if (td->ftp_mpm_thread_ctx != NULL) {
304  }
305 
306  SCFree(td);
307  }
308 
309  return;
310 }
311 static FTPTransaction *FTPTransactionCreate(FtpState *state)
312 {
313  SCEnter();
314  FTPTransaction *tx = FTPCalloc(1, sizeof(*tx));
315  if (tx == NULL) {
316  return NULL;
317  }
318 
319  TAILQ_INSERT_TAIL(&state->tx_list, tx, next);
320  tx->tx_id = state->tx_cnt++;
321 
322  TAILQ_INIT(&tx->response_list);
323 
324  SCLogDebug("new transaction %p (state tx cnt %"PRIu64")", tx, state->tx_cnt);
325  return tx;
326 }
327 
328 static void FTPTransactionFree(FTPTransaction *tx)
329 {
330  SCEnter();
331 
332  if (tx->de_state != NULL) {
334  }
335 
336  if (tx->request) {
337  FTPFree(tx->request, tx->request_length);
338  }
339 
340  FTPString *str = NULL;
341  while ((str = TAILQ_FIRST(&tx->response_list))) {
342  TAILQ_REMOVE(&tx->response_list, str, next);
343  FTPStringFree(str);
344  }
345 
346  FTPFree(tx, sizeof(*tx));
347 }
348 
349 static int FTPGetLineForDirection(FtpState *state, FtpLineState *line_state)
350 {
351  void *ptmp;
352  if (line_state->current_line_lf_seen == 1) {
353  /* we have seen the lf for the previous line. Clear the parser
354  * details to parse new line */
355  line_state->current_line_lf_seen = 0;
356  if (line_state->current_line_db == 1) {
357  line_state->current_line_db = 0;
358  FTPFree(line_state->db, line_state->db_len);
359  line_state->db = NULL;
360  line_state->db_len = 0;
361  state->current_line = NULL;
362  state->current_line_len = 0;
363  }
364  }
365 
366  uint8_t *lf_idx = memchr(state->input, 0x0a, state->input_len);
367 
368  if (lf_idx == NULL) {
369  /* fragmented lines. Decoder event for special cases. Not all
370  * fragmented lines should be treated as a possible evasion
371  * attempt. With multi payload ftp chunks we can have valid
372  * cases of fragmentation. But within the same segment chunk
373  * if we see fragmentation then it's definitely something you
374  * should alert about */
375  if (line_state->current_line_db == 0) {
376  line_state->db = FTPMalloc(state->input_len);
377  if (line_state->db == NULL) {
378  return -1;
379  }
380  line_state->current_line_db = 1;
381  memcpy(line_state->db, state->input, state->input_len);
382  line_state->db_len = state->input_len;
383  } else {
384  ptmp = FTPRealloc(line_state->db, line_state->db_len,
385  (line_state->db_len + state->input_len));
386  if (ptmp == NULL) {
387  FTPFree(line_state->db, line_state->db_len);
388  line_state->db = NULL;
389  line_state->db_len = 0;
390  return -1;
391  }
392  line_state->db = ptmp;
393 
394  memcpy(line_state->db + line_state->db_len,
395  state->input, state->input_len);
396  line_state->db_len += state->input_len;
397  }
398  state->input += state->input_len;
399  state->input_len = 0;
400 
401  return -1;
402 
403  } else {
404  line_state->current_line_lf_seen = 1;
405 
406  if (line_state->current_line_db == 1) {
407  ptmp = FTPRealloc(line_state->db, line_state->db_len,
408  (line_state->db_len + (lf_idx + 1 - state->input)));
409  if (ptmp == NULL) {
410  FTPFree(line_state->db, line_state->db_len);
411  line_state->db = NULL;
412  line_state->db_len = 0;
413  return -1;
414  }
415  line_state->db = ptmp;
416 
417  memcpy(line_state->db + line_state->db_len,
418  state->input, (lf_idx + 1 - state->input));
419  line_state->db_len += (lf_idx + 1 - state->input);
420 
421  if (line_state->db_len > 1 &&
422  line_state->db[line_state->db_len - 2] == 0x0D) {
423  line_state->db_len -= 2;
424  state->current_line_delimiter_len = 2;
425  } else {
426  line_state->db_len -= 1;
427  state->current_line_delimiter_len = 1;
428  }
429 
430  state->current_line = line_state->db;
431  state->current_line_len = line_state->db_len;
432 
433  } else {
434  state->current_line = state->input;
435  state->current_line_len = lf_idx - state->input;
436 
437  if (state->input != lf_idx &&
438  *(lf_idx - 1) == 0x0D) {
439  state->current_line_len--;
440  state->current_line_delimiter_len = 2;
441  } else {
442  state->current_line_delimiter_len = 1;
443  }
444  }
445 
446  state->input_len -= (lf_idx - state->input) + 1;
447  state->input = (lf_idx + 1);
448 
449  return 0;
450  }
451 
452 }
453 
454 static int FTPGetLine(FtpState *state)
455 {
456  SCEnter();
457 
458  /* we have run out of input */
459  if (state->input_len <= 0)
460  return -1;
461 
462  /* toserver */
463  if (state->direction == 0)
464  return FTPGetLineForDirection(state, &state->line_state[0]);
465  else
466  return FTPGetLineForDirection(state, &state->line_state[1]);
467 }
468 
469 /**
470  * \brief This function is called to determine and set which command is being
471  * transferred to the ftp server
472  * \param thread context
473  * \param input input line of the command
474  * \param len of the command
475  * \param cmd_descriptor when the command has been parsed
476  *
477  * \retval 1 when the command is parsed, 0 otherwise
478  */
479 static int FTPParseRequestCommand(FTPThreadCtx *td,
480  const uint8_t *input, uint32_t input_len,
481  const FtpCommand **cmd_descriptor)
482 {
483  SCEnter();
484 
485  /* I don't like this pmq reset here. We'll devise a method later, that
486  * should make the use of the mpm very efficient */
487  PmqReset(td->pmq);
488  int mpm_cnt = mpm_table[FTP_MPM].Search(ftp_mpm_ctx, td->ftp_mpm_thread_ctx,
489  td->pmq, input, input_len);
490  if (mpm_cnt) {
491  *cmd_descriptor = &FtpCommands[td->pmq->rule_id_array[0]];
492  SCReturnInt(1);
493  }
494 
495  *cmd_descriptor = NULL;
496  SCReturnInt(0);
497 }
498 
500  /** Need to look like a ExpectationData so DFree must
501  * be first field . */
502  void (*DFree)(void *);
503  uint64_t flow_id;
504  uint8_t *file_name;
505  uint16_t file_len;
507 };
508 
509 static void FtpTransferCmdFree(void *data)
510 {
511  struct FtpTransferCmd *cmd = (struct FtpTransferCmd *) data;
512  if (cmd == NULL)
513  return;
514  if (cmd->file_name) {
515  FTPFree(cmd->file_name, cmd->file_len + 1);
516  }
517  FTPFree(cmd, sizeof(struct FtpTransferCmd));
518 }
519 
520 static uint32_t CopyCommandLine(uint8_t **dest, const uint8_t *src, uint32_t length)
521 {
522  if (likely(length)) {
523  uint8_t *where = FTPCalloc(length + 1, sizeof(char));
524  if (unlikely(where == NULL)) {
525  return 0;
526  }
527  memcpy(where, src, length);
528 
529  /* Remove trailing newlines/carriage returns */
530  while (length && isspace((unsigned char) where[length - 1])) {
531  length--;
532  }
533 
534  where[length] = '\0';
535  *dest = where;
536  }
537  /* either 0 or actual */
538  return length ? length + 1 : 0;
539 }
540 
541 
542 /**
543  * \brief This function is called to retrieve a ftp request
544  * \param ftp_state the ftp state structure for the parser
545  * \param input input line of the command
546  * \param input_len length of the request
547  * \param output the resulting output
548  *
549  * \retval APP_LAYER_OK when input was process successfully
550  * \retval APP_LAYER_ERROR when a unrecoverable error was encountered
551  */
552 static AppLayerResult FTPParseRequest(Flow *f, void *ftp_state,
553  AppLayerParserState *pstate,
554  const uint8_t *input, uint32_t input_len,
555  void *local_data, const uint8_t flags)
556 {
557  FTPThreadCtx *thread_data = local_data;
558 
559  SCEnter();
560  /* PrintRawDataFp(stdout, input,input_len); */
561 
562  FtpState *state = (FtpState *)ftp_state;
563  void *ptmp;
564 
565  if (input == NULL && AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF)) {
567  } else if (input == NULL || input_len == 0) {
569  }
570 
571  state->input = input;
572  state->input_len = input_len;
573  /* toserver stream */
574  state->direction = 0;
575 
576  int direction = STREAM_TOSERVER;
577  while (FTPGetLine(state) >= 0) {
578  const FtpCommand *cmd_descriptor;
579 
580  if (!FTPParseRequestCommand(thread_data,
581  state->current_line, state->current_line_len,
582  &cmd_descriptor)) {
583  state->command = FTP_COMMAND_UNKNOWN;
584  continue;
585  }
586 
587  state->command = cmd_descriptor->command;
588 
589  FTPTransaction *tx = FTPTransactionCreate(state);
590  if (unlikely(tx == NULL))
592  state->curr_tx = tx;
593 
594  tx->command_descriptor = cmd_descriptor;
595  tx->request_length = CopyCommandLine(&tx->request,
596  state->current_line, state->current_line_len);
597 
598  switch (state->command) {
599  case FTP_COMMAND_EPRT:
600  // fallthrough
601  case FTP_COMMAND_PORT:
602  if (state->current_line_len + 1 > state->port_line_size) {
603  /* Allocate an extra byte for a NULL terminator */
604  ptmp = FTPRealloc(state->port_line, state->port_line_size,
605  state->current_line_len);
606  if (ptmp == NULL) {
607  if (state->port_line) {
608  FTPFree(state->port_line, state->port_line_size);
609  state->port_line = NULL;
610  state->port_line_size = 0;
611  }
613  }
614  state->port_line = ptmp;
615  state->port_line_size = state->current_line_len;
616  }
617  memcpy(state->port_line, state->current_line,
618  state->current_line_len);
619  state->port_line_len = state->current_line_len;
620  break;
621  case FTP_COMMAND_RETR:
622  /* change direction (default to server) so expectation will handle
623  * the correct message when expectation will match.
624  */
625  direction = STREAM_TOCLIENT;
626  // fallthrough
627  case FTP_COMMAND_STOR: {
628  /* Ensure that there is a negotiated dyn port and a file
629  * name -- need more than 5 chars: cmd [4], space, <filename>
630  */
631  if (state->dyn_port == 0 || state->current_line_len < 6) {
633  }
634  struct FtpTransferCmd *data = FTPCalloc(1, sizeof(struct FtpTransferCmd));
635  if (data == NULL)
637  data->DFree = FtpTransferCmdFree;
638  /* Min size has been checked in FTPParseRequestCommand */
639  data->file_name = FTPCalloc(state->current_line_len - 4, sizeof(char));
640  if (data->file_name == NULL) {
641  FtpTransferCmdFree(data);
643  }
644  data->file_name[state->current_line_len - 5] = 0;
645  data->file_len = state->current_line_len - 5;
646  memcpy(data->file_name, state->current_line + 5, state->current_line_len - 5);
647  data->cmd = state->command;
648  data->flow_id = FlowGetId(f);
649  int ret = AppLayerExpectationCreate(f,
650  state->active ? STREAM_TOSERVER : direction,
651  0, state->dyn_port, ALPROTO_FTPDATA, data);
652  if (ret == -1) {
653  FtpTransferCmdFree(data);
654  SCLogDebug("No expectation created.");
656  } else {
657  SCLogDebug("Expectation created [direction: %s, dynamic port %"PRIu16"].",
658  state->active ? "to server" : "to client",
659  state->dyn_port);
660  }
661 
662  /* reset the dyn port to avoid duplicate */
663  state->dyn_port = 0;
664  /* reset active/passive indicator */
665  state->active = false;
666  }
667  break;
668  default:
669  break;
670  }
671  }
672 
674 }
675 
676 static int FTPParsePassiveResponse(Flow *f, FtpState *state, const uint8_t *input, uint32_t input_len)
677 {
678  uint16_t dyn_port = rs_ftp_pasv_response(input, input_len);
679  if (dyn_port == 0) {
680  return -1;
681  }
682  SCLogDebug("FTP passive mode (v4): dynamic port %"PRIu16"", dyn_port);
683  state->active = false;
684  state->dyn_port = dyn_port;
685  state->curr_tx->dyn_port = dyn_port;
686  state->curr_tx->active = false;
687 
688  return 0;
689 }
690 
691 static int FTPParsePassiveResponseV6(Flow *f, FtpState *state, const uint8_t *input, uint32_t input_len)
692 {
693  uint16_t dyn_port = rs_ftp_epsv_response(input, input_len);
694  if (dyn_port == 0) {
695  return -1;
696  }
697  SCLogDebug("FTP passive mode (v6): dynamic port %"PRIu16"", dyn_port);
698  state->active = false;
699  state->dyn_port = dyn_port;
700  state->curr_tx->dyn_port = dyn_port;
701  state->curr_tx->active = false;
702  return 0;
703 }
704 
705 /**
706  * \brief Handle preliminary replies -- keep tx open
707  * \retval bool True for a positive preliminary reply; false otherwise
708  *
709  * 1yz Positive Preliminary reply
710  *
711  * The requested action is being initiated; expect another
712  * reply before proceeding with a new command
713  */
714 static inline bool FTPIsPPR(const uint8_t *input, uint32_t input_len)
715 {
716  return input_len >= 4 && isdigit(input[0]) && input[0] == '1' &&
717  isdigit(input[1]) && isdigit(input[2]) && isspace(input[3]);
718 }
719 
720 /**
721  * \brief This function is called to retrieve a ftp response
722  * \param ftp_state the ftp state structure for the parser
723  * \param input input line of the command
724  * \param input_len length of the request
725  * \param output the resulting output
726  *
727  * \retval 1 when the command is parsed, 0 otherwise
728  */
729 static AppLayerResult FTPParseResponse(Flow *f, void *ftp_state, AppLayerParserState *pstate,
730  const uint8_t *input, uint32_t input_len,
731  void *local_data, const uint8_t flags)
732 {
733  FtpState *state = (FtpState *)ftp_state;
734 
735  if (unlikely(input_len == 0)) {
737  }
738  state->input = input;
739  state->input_len = input_len;
740  /* toclient stream */
741  state->direction = 1;
742 
743  while (FTPGetLine(state) >= 0) {
744  FTPTransaction *tx = FTPGetOldestTx(state);
745  if (tx == NULL) {
746  tx = FTPTransactionCreate(state);
747  }
748  if (unlikely(tx == NULL)) {
750  }
751  if (state->command == FTP_COMMAND_UNKNOWN || tx->command_descriptor == NULL) {
752  /* unknown */
754  }
755 
756  state->curr_tx = tx;
757  uint16_t dyn_port;
758  switch (state->command) {
760  if (state->current_line_len >= 4 && SCMemcmp("234 ", state->current_line, 4) == 0) {
762  }
763  break;
764 
765  case FTP_COMMAND_EPRT:
766  dyn_port = rs_ftp_active_eprt(state->port_line, state->port_line_len);
767  if (dyn_port == 0) {
768  goto tx_complete;
769  }
770  state->dyn_port = dyn_port;
771  state->active = true;
772  tx->dyn_port = dyn_port;
773  tx->active = true;
774  SCLogDebug("FTP active mode (v6): dynamic port %"PRIu16"", dyn_port);
775  break;
776 
777  case FTP_COMMAND_PORT:
778  dyn_port = rs_ftp_active_port(state->port_line, state->port_line_len);
779  if (dyn_port == 0) {
780  goto tx_complete;
781  }
782  state->dyn_port = dyn_port;
783  state->active = true;
784  tx->dyn_port = state->dyn_port;
785  tx->active = true;
786  SCLogDebug("FTP active mode (v4): dynamic port %"PRIu16"", dyn_port);
787  break;
788 
789  case FTP_COMMAND_PASV:
790  if (state->current_line_len >= 4 && SCMemcmp("227 ", state->current_line, 4) == 0) {
791  FTPParsePassiveResponse(f, ftp_state, state->current_line, state->current_line_len);
792  }
793  break;
794 
795  case FTP_COMMAND_EPSV:
796  if (state->current_line_len >= 4 && SCMemcmp("229 ", state->current_line, 4) == 0) {
797  FTPParsePassiveResponseV6(f, ftp_state, state->current_line, state->current_line_len);
798  }
799  break;
800  default:
801  break;
802  }
803 
804  if (likely(state->current_line_len)) {
805  FTPString *response = FTPStringAlloc();
806  if (likely(response)) {
807  response->len = CopyCommandLine(&response->str, state->current_line, state->current_line_len);
808  TAILQ_INSERT_TAIL(&tx->response_list, response, next);
809  }
810  }
811 
812  /* Handle preliminary replies -- keep tx open */
813  if (FTPIsPPR(state->current_line, state->current_line_len)) {
814  continue;
815  }
816  tx_complete:
817  tx->done = true;
818  }
819 
821 }
822 
823 
824 #ifdef DEBUG
825 static SCMutex ftp_state_mem_lock = SCMUTEX_INITIALIZER;
826 static uint64_t ftp_state_memuse = 0;
827 static uint64_t ftp_state_memcnt = 0;
828 #endif
829 
830 static void *FTPStateAlloc(void)
831 {
832  void *s = FTPCalloc(1, sizeof(FtpState));
833  if (unlikely(s == NULL))
834  return NULL;
835 
836  FtpState *ftp_state = (FtpState *) s;
837  TAILQ_INIT(&ftp_state->tx_list);
838 
839 #ifdef DEBUG
840  SCMutexLock(&ftp_state_mem_lock);
841  ftp_state_memcnt++;
842  ftp_state_memuse+=sizeof(FtpState);
843  SCMutexUnlock(&ftp_state_mem_lock);
844 #endif
845  return s;
846 }
847 
848 static void FTPStateFree(void *s)
849 {
850  FtpState *fstate = (FtpState *) s;
851  if (fstate->port_line != NULL)
852  FTPFree(fstate->port_line, fstate->port_line_size);
853  if (fstate->line_state[0].db)
854  FTPFree(fstate->line_state[0].db, fstate->line_state[0].db_len);
855  if (fstate->line_state[1].db)
856  FTPFree(fstate->line_state[1].db, fstate->line_state[1].db_len);
857 
858  //AppLayerDecoderEventsFreeEvents(&s->decoder_events);
859 
860  FTPTransaction *tx = NULL;
861  while ((tx = TAILQ_FIRST(&fstate->tx_list))) {
862  TAILQ_REMOVE(&fstate->tx_list, tx, next);
863  SCLogDebug("[%s] state %p id %"PRIu64", Freeing %d bytes at %p",
865  s, tx->tx_id,
866  tx->request_length, tx->request);
867  FTPTransactionFree(tx);
868  }
869 
870  FTPFree(s, sizeof(FtpState));
871 #ifdef DEBUG
872  SCMutexLock(&ftp_state_mem_lock);
873  ftp_state_memcnt--;
874  ftp_state_memuse-=sizeof(FtpState);
875  SCMutexUnlock(&ftp_state_mem_lock);
876 #endif
877 }
878 
879 static int FTPSetTxDetectState(void *vtx, DetectEngineState *de_state)
880 {
881  FTPTransaction *tx = (FTPTransaction *)vtx;
882  tx->de_state = de_state;
883  return 0;
884 }
885 
886 /**
887  * \brief This function returns the oldest open transaction; if none
888  * are open, then the oldest transaction is returned
889  * \param ftp_state the ftp state structure for the parser
890  *
891  * \retval transaction pointer when a transaction was found; NULL otherwise.
892  */
893 static FTPTransaction *FTPGetOldestTx(FtpState *ftp_state)
894 {
895  if (unlikely(!ftp_state)) {
896  SCLogDebug("NULL state object; no transactions available");
897  return NULL;
898  }
899  FTPTransaction *tx = NULL;
900  FTPTransaction *lasttx = NULL;
901  TAILQ_FOREACH(tx, &ftp_state->tx_list, next) {
902  /* Return oldest open tx */
903  if (!tx->done) {
904  SCLogDebug("Returning tx %p id %"PRIu64, tx, tx->tx_id);
905  return tx;
906  }
907  /* save for the end */
908  lasttx = tx;
909  }
910  /* All tx are closed; return last element */
911  if (lasttx)
912  SCLogDebug("Returning OLDEST tx %p id %"PRIu64, lasttx, lasttx->tx_id);
913  return lasttx;
914 }
915 
916 static void *FTPGetTx(void *state, uint64_t tx_id)
917 {
918  FtpState *ftp_state = (FtpState *)state;
919  if (ftp_state) {
920  FTPTransaction *tx = NULL;
921 
922  if (ftp_state->curr_tx == NULL)
923  return NULL;
924  if (ftp_state->curr_tx->tx_id == tx_id)
925  return ftp_state->curr_tx;
926 
927  TAILQ_FOREACH(tx, &ftp_state->tx_list, next) {
928  if (tx->tx_id == tx_id)
929  return tx;
930  }
931  }
932  return NULL;
933 }
934 
935 static DetectEngineState *FTPGetTxDetectState(void *vtx)
936 {
937  FTPTransaction *tx = (FTPTransaction *)vtx;
938  return tx->de_state;
939 }
940 
941 
942 static uint64_t FTPGetTxDetectFlags(void *vtx, uint8_t dir)
943 {
944  FTPTransaction *tx = (FTPTransaction *)vtx;
945  if (dir & STREAM_TOSERVER) {
946  return tx->detect_flags_ts;
947  } else {
948  return tx->detect_flags_tc;
949  }
950 }
951 
952 static void FTPSetTxDetectFlags(void *vtx, uint8_t dir, uint64_t flags)
953 {
954  FTPTransaction *tx = (FTPTransaction *)vtx;
955  if (dir & STREAM_TOSERVER) {
956  tx->detect_flags_ts = flags;
957  } else {
958  tx->detect_flags_tc = flags;
959  }
960 }
961 
962 static void FTPStateTransactionFree(void *state, uint64_t tx_id)
963 {
964  FtpState *ftp_state = state;
965  FTPTransaction *tx = NULL;
966  TAILQ_FOREACH(tx, &ftp_state->tx_list, next) {
967  if (tx_id < tx->tx_id)
968  break;
969  else if (tx_id > tx->tx_id)
970  continue;
971 
972  if (tx == ftp_state->curr_tx)
973  ftp_state->curr_tx = NULL;
974  TAILQ_REMOVE(&ftp_state->tx_list, tx, next);
975  FTPTransactionFree(tx);
976  break;
977  }
978 }
979 
980 static uint64_t FTPGetTxCnt(void *state)
981 {
982  uint64_t cnt = 0;
983  FtpState *ftp_state = state;
984  if (ftp_state) {
985  cnt = ftp_state->tx_cnt;
986  }
987  SCLogDebug("returning state %p %"PRIu64, state, cnt);
988  return cnt;
989 }
990 
991 static int FTPGetAlstateProgressCompletionStatus(uint8_t direction)
992 {
993  return FTP_STATE_FINISHED;
994 }
995 
996 static int FTPGetAlstateProgress(void *vtx, uint8_t direction)
997 {
998  SCLogDebug("tx %p", vtx);
999  FTPTransaction *tx = vtx;
1000 
1001  if (!tx->done) {
1002  if (direction == STREAM_TOSERVER &&
1004  return FTP_STATE_PORT_DONE;
1005  }
1006  return FTP_STATE_IN_PROGRESS;
1007  }
1008 
1009  return FTP_STATE_FINISHED;
1010 }
1011 
1012 
1013 static int FTPRegisterPatternsForProtocolDetection(void)
1014 {
1016  "220 (", 5, 0, STREAM_TOCLIENT) < 0)
1017  {
1018  return -1;
1019  }
1021  "FEAT", 4, 0, STREAM_TOSERVER) < 0)
1022  {
1023  return -1;
1024  }
1026  "USER ", 5, 0, STREAM_TOSERVER) < 0)
1027  {
1028  return -1;
1029  }
1031  "PASS ", 5, 0, STREAM_TOSERVER) < 0)
1032  {
1033  return -1;
1034  }
1036  "PORT ", 5, 0, STREAM_TOSERVER) < 0)
1037  {
1038  return -1;
1039  }
1040 
1041  return 0;
1042 }
1043 
1044 
1046 
1047 /**
1048  * \brief This function is called to retrieve a ftp request
1049  * \param ftp_state the ftp state structure for the parser
1050  * \param input input line of the command
1051  * \param input_len length of the request
1052  * \param output the resulting output
1053  *
1054  * \retval 1 when the command is parsed, 0 otherwise
1055  */
1056 static AppLayerResult FTPDataParse(Flow *f, FtpDataState *ftpdata_state,
1057  AppLayerParserState *pstate,
1058  const uint8_t *input, uint32_t input_len,
1059  void *local_data, int direction)
1060 {
1061  uint16_t flags = FileFlowToFlags(f, direction);
1062  int ret = 0;
1063  /* we depend on detection engine for file pruning */
1065  if (ftpdata_state->files == NULL) {
1067  if (data == NULL) {
1069  }
1070 
1071  ftpdata_state->files = FileContainerAlloc();
1072  if (ftpdata_state->files == NULL) {
1075  }
1076 
1077  ftpdata_state->file_name = data->file_name;
1078  ftpdata_state->file_len = data->file_len;
1079  data->file_name = NULL;
1080  data->file_len = 0;
1081  f->parent_id = data->flow_id;
1082  ftpdata_state->command = data->cmd;
1083  switch (data->cmd) {
1084  case FTP_COMMAND_STOR:
1085  ftpdata_state->direction = STREAM_TOSERVER;
1086  break;
1087  case FTP_COMMAND_RETR:
1088  ftpdata_state->direction = STREAM_TOCLIENT;
1089  break;
1090  default:
1091  break;
1092  }
1093 
1094  /* open with fixed track_id 0 as we can have just one
1095  * file per ftp-data flow. */
1096  if (FileOpenFileWithId(ftpdata_state->files, &sbcfg,
1097  0ULL, (uint8_t *) ftpdata_state->file_name,
1098  ftpdata_state->file_len,
1099  input, input_len, flags) != 0) {
1100  SCLogDebug("Can't open file");
1101  ret = -1;
1102  }
1104  } else {
1105  if (input_len != 0) {
1106  ret = FileAppendData(ftpdata_state->files, input, input_len);
1107  if (ret == -2) {
1108  ret = 0;
1109  SCLogDebug("FileAppendData() - file no longer being extracted");
1110  goto out;
1111  } else if (ret < 0) {
1112  SCLogDebug("FileAppendData() failed: %d", ret);
1113  ret = -2;
1114  goto out;
1115  }
1116  } else {
1117  ret = FileCloseFile(ftpdata_state->files, NULL, 0, flags);
1118  ftpdata_state->state = FTPDATA_STATE_FINISHED;
1119  if (ret < 0)
1120  goto out;
1121  }
1122  }
1123 
1124  if (input_len && AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF)) {
1125  ret = FileCloseFile(ftpdata_state->files, (uint8_t *) NULL, 0, flags);
1126  ftpdata_state->state = FTPDATA_STATE_FINISHED;
1127  }
1128 
1129 out:
1130  if (ret < 0) {
1132  }
1134 }
1135 
1136 static void FTPStateSetTxLogged(void *state, void *vtx, LoggerId logged)
1137 {
1138  FTPTransaction *tx = vtx;
1139  tx->logged = logged;
1140 }
1141 
1142 static LoggerId FTPStateGetTxLogged(void *state, void *vtx)
1143 {
1144  FTPTransaction *tx = vtx;
1145  return tx->logged;
1146 }
1147 static AppLayerResult FTPDataParseRequest(Flow *f, void *ftp_state,
1148  AppLayerParserState *pstate,
1149  const uint8_t *input, uint32_t input_len,
1150  void *local_data, const uint8_t flags)
1151 {
1152  return FTPDataParse(f, ftp_state, pstate, input, input_len,
1153  local_data, STREAM_TOSERVER);
1154 }
1155 
1156 static AppLayerResult FTPDataParseResponse(Flow *f, void *ftp_state,
1157  AppLayerParserState *pstate,
1158  const uint8_t *input, uint32_t input_len,
1159  void *local_data, const uint8_t flags)
1160 {
1161  return FTPDataParse(f, ftp_state, pstate, input, input_len,
1162  local_data, STREAM_TOCLIENT);
1163 }
1164 
1165 #ifdef DEBUG
1166 static SCMutex ftpdata_state_mem_lock = SCMUTEX_INITIALIZER;
1167 static uint64_t ftpdata_state_memuse = 0;
1168 static uint64_t ftpdata_state_memcnt = 0;
1169 #endif
1170 
1171 static void *FTPDataStateAlloc(void)
1172 {
1173  void *s = FTPCalloc(1, sizeof(FtpDataState));
1174  if (unlikely(s == NULL))
1175  return NULL;
1176 
1177  FtpDataState *state = (FtpDataState *) s;
1179 
1180 #ifdef DEBUG
1181  SCMutexLock(&ftpdata_state_mem_lock);
1182  ftpdata_state_memcnt++;
1183  ftpdata_state_memuse+=sizeof(FtpDataState);
1184  SCMutexUnlock(&ftpdata_state_mem_lock);
1185 #endif
1186  return s;
1187 }
1188 
1189 static void FTPDataStateFree(void *s)
1190 {
1191  FtpDataState *fstate = (FtpDataState *) s;
1192 
1193  if (fstate->de_state != NULL) {
1195  }
1196  if (fstate->file_name != NULL) {
1197  FTPFree(fstate->file_name, fstate->file_len + 1);
1198  }
1199 
1200  FileContainerFree(fstate->files);
1201 
1202  FTPFree(s, sizeof(FtpDataState));
1203 #ifdef DEBUG
1204  SCMutexLock(&ftpdata_state_mem_lock);
1205  ftpdata_state_memcnt--;
1206  ftpdata_state_memuse-=sizeof(FtpDataState);
1207  SCMutexUnlock(&ftpdata_state_mem_lock);
1208 #endif
1209 }
1210 
1211 static int FTPDataSetTxDetectState(void *vtx, DetectEngineState *de_state)
1212 {
1213  FtpDataState *ftp_state = (FtpDataState *)vtx;
1214  ftp_state->de_state = de_state;
1215  return 0;
1216 }
1217 
1218 static DetectEngineState *FTPDataGetTxDetectState(void *vtx)
1219 {
1220  FtpDataState *ftp_state = (FtpDataState *)vtx;
1221  return ftp_state->de_state;
1222 }
1223 
1224 static void FTPDataSetTxDetectFlags(void *vtx, uint8_t dir, uint64_t flags)
1225 {
1226  FtpDataState *ftp_state = (FtpDataState *)vtx;
1227  if (dir & STREAM_TOSERVER) {
1228  ftp_state->detect_flags_ts = flags;
1229  } else {
1230  ftp_state->detect_flags_tc = flags;
1231  }
1232 }
1233 
1234 static uint64_t FTPDataGetTxDetectFlags(void *vtx, uint8_t dir)
1235 {
1236  FtpDataState *ftp_state = (FtpDataState *)vtx;
1237  if (dir & STREAM_TOSERVER) {
1238  return ftp_state->detect_flags_ts;
1239  } else {
1240  return ftp_state->detect_flags_tc;
1241  }
1242 }
1243 
1244 static void FTPDataStateTransactionFree(void *state, uint64_t tx_id)
1245 {
1246  /* do nothing */
1247 }
1248 
1249 static void *FTPDataGetTx(void *state, uint64_t tx_id)
1250 {
1251  FtpDataState *ftp_state = (FtpDataState *)state;
1252  return ftp_state;
1253 }
1254 
1255 static uint64_t FTPDataGetTxCnt(void *state)
1256 {
1257  /* ftp-data is single tx */
1258  return 1;
1259 }
1260 
1261 static int FTPDataGetAlstateProgressCompletionStatus(uint8_t direction)
1262 {
1263  return FTPDATA_STATE_FINISHED;
1264 }
1265 
1266 static int FTPDataGetAlstateProgress(void *tx, uint8_t direction)
1267 {
1268  FtpDataState *ftpdata_state = (FtpDataState *)tx;
1269  return ftpdata_state->state;
1270 }
1271 
1272 static FileContainer *FTPDataStateGetFiles(void *state, uint8_t direction)
1273 {
1274  FtpDataState *ftpdata_state = (FtpDataState *)state;
1275 
1276  if (direction != ftpdata_state->direction)
1277  SCReturnPtr(NULL, "FileContainer");
1278 
1279  SCReturnPtr(ftpdata_state->files, "FileContainer");
1280 }
1281 
1282 static void FTPSetMpmState(void)
1283 {
1284  ftp_mpm_ctx = SCMalloc(sizeof(MpmCtx));
1285  if (unlikely(ftp_mpm_ctx == NULL)) {
1286  exit(EXIT_FAILURE);
1287  }
1288  memset(ftp_mpm_ctx, 0, sizeof(MpmCtx));
1289  MpmInitCtx(ftp_mpm_ctx, FTP_MPM);
1290 
1291  uint32_t i = 0;
1292  for (i = 0; i < sizeof(FtpCommands)/sizeof(FtpCommand) - 1; i++) {
1293  const FtpCommand *cmd = &FtpCommands[i];
1294  if (cmd->command_length == 0)
1295  continue;
1296 
1297  MpmAddPatternCI(ftp_mpm_ctx,
1298  (uint8_t *)cmd->command_name,
1299  cmd->command_length,
1300  0 /* defunct */, 0 /* defunct */,
1301  i /* id */, i /* rule id */ , 0 /* no flags */);
1302  }
1303 
1304  mpm_table[FTP_MPM].Prepare(ftp_mpm_ctx);
1305 
1306 }
1307 
1308 static void FTPFreeMpmState(void)
1309 {
1310  if (ftp_mpm_ctx != NULL) {
1311  mpm_table[FTP_MPM].DestroyCtx(ftp_mpm_ctx);
1312  SCFree(ftp_mpm_ctx);
1313  ftp_mpm_ctx = NULL;
1314  }
1315 }
1316 
1318 {
1319  const char *proto_name = "ftp";
1320  const char *proto_data_name = "ftp-data";
1321 
1322  /** FTP */
1323  if (AppLayerProtoDetectConfProtoDetectionEnabled("tcp", proto_name)) {
1325  if (FTPRegisterPatternsForProtocolDetection() < 0 )
1326  return;
1328  }
1329 
1330  if (AppLayerParserConfParserEnabled("tcp", proto_name)) {
1332  FTPParseRequest);
1334  FTPParseResponse);
1335  AppLayerParserRegisterStateFuncs(IPPROTO_TCP, ALPROTO_FTP, FTPStateAlloc, FTPStateFree);
1337 
1338  AppLayerParserRegisterTxFreeFunc(IPPROTO_TCP, ALPROTO_FTP, FTPStateTransactionFree);
1339 
1341  FTPGetTxDetectState, FTPSetTxDetectState);
1342 
1344  FTPGetTxDetectFlags, FTPSetTxDetectFlags);
1345 
1346  AppLayerParserRegisterGetTx(IPPROTO_TCP, ALPROTO_FTP, FTPGetTx);
1347  AppLayerParserRegisterLoggerFuncs(IPPROTO_TCP, ALPROTO_FTP, FTPStateGetTxLogged,
1348  FTPStateSetTxLogged);
1349 
1350  AppLayerParserRegisterLocalStorageFunc(IPPROTO_TCP, ALPROTO_FTP, FTPLocalStorageAlloc,
1351  FTPLocalStorageFree);
1352  AppLayerParserRegisterGetTxCnt(IPPROTO_TCP, ALPROTO_FTP, FTPGetTxCnt);
1353 
1354  AppLayerParserRegisterGetStateProgressFunc(IPPROTO_TCP, ALPROTO_FTP, FTPGetAlstateProgress);
1355 
1357  FTPGetAlstateProgressCompletionStatus);
1358 
1359 
1362  FTPDataParseRequest);
1364  FTPDataParseResponse);
1365  AppLayerParserRegisterStateFuncs(IPPROTO_TCP, ALPROTO_FTPDATA, FTPDataStateAlloc, FTPDataStateFree);
1367  AppLayerParserRegisterTxFreeFunc(IPPROTO_TCP, ALPROTO_FTPDATA, FTPDataStateTransactionFree);
1369  FTPDataGetTxDetectState, FTPDataSetTxDetectState);
1371  FTPDataGetTxDetectFlags, FTPDataSetTxDetectFlags);
1372 
1373  AppLayerParserRegisterGetFilesFunc(IPPROTO_TCP, ALPROTO_FTPDATA, FTPDataStateGetFiles);
1374 
1375  AppLayerParserRegisterGetTx(IPPROTO_TCP, ALPROTO_FTPDATA, FTPDataGetTx);
1376 
1377  AppLayerParserRegisterGetTxCnt(IPPROTO_TCP, ALPROTO_FTPDATA, FTPDataGetTxCnt);
1378 
1379  AppLayerParserRegisterGetStateProgressFunc(IPPROTO_TCP, ALPROTO_FTPDATA, FTPDataGetAlstateProgress);
1380 
1382  FTPDataGetAlstateProgressCompletionStatus);
1383 
1384  sbcfg.buf_size = 4096;
1385  sbcfg.Malloc = FTPMalloc;
1386  sbcfg.Calloc = FTPCalloc;
1387  sbcfg.Realloc = FTPRealloc;
1388  sbcfg.Free = FTPFree;
1389 
1390  FTPParseMemcap();
1391  } else {
1392  SCLogInfo("Parsed disabled for %s protocol. Protocol detection"
1393  "still on.", proto_name);
1394  }
1395 
1396  FTPSetMpmState();
1397 
1398 #ifdef UNITTESTS
1400 #endif
1401 }
1402 
1404 {
1405 #ifdef DEBUG
1406  SCMutexLock(&ftp_state_mem_lock);
1407  SCLogDebug("ftp_state_memcnt %"PRIu64", ftp_state_memuse %"PRIu64"",
1408  ftp_state_memcnt, ftp_state_memuse);
1409  SCMutexUnlock(&ftp_state_mem_lock);
1410 #endif
1411 }
1412 
1413 
1414 /*
1415  * \brief Returns the ending offset of the next line from a multi-line buffer.
1416  *
1417  * "Buffer" refers to a FTP response in a single buffer containing multiple lines.
1418  * Here, "next line" is defined as terminating on
1419  * - Newline character
1420  * - Null character
1421  *
1422  * \param buffer Contains zero or more characters.
1423  * \param len Size, in bytes, of buffer.
1424  *
1425  * \retval Offset from the start of buffer indicating the where the
1426  * next "line ends". The characters between the input buffer and this
1427  * value comprise the line.
1428  *
1429  * NULL is found first or a newline isn't found, then UINT16_MAX is returned.
1430  */
1431 uint16_t JsonGetNextLineFromBuffer(const char *buffer, const uint16_t len)
1432 {
1433  if (!buffer || *buffer == '\0') {
1434  return UINT16_MAX;
1435  }
1436 
1437  char *c = strchr(buffer, '\n');
1438  return c == NULL ? len : c - buffer + 1;
1439 }
1440 
1441 void EveFTPDataAddMetadata(const Flow *f, JsonBuilder *jb)
1442 {
1443  const FtpDataState *ftp_state = NULL;
1444  if (f->alstate == NULL)
1445  return;
1446 
1447  ftp_state = (FtpDataState *)f->alstate;
1448 
1449  if (ftp_state->file_name) {
1450  jb_set_string_from_bytes(jb, "filename", ftp_state->file_name, ftp_state->file_len);
1451  }
1452  switch (ftp_state->command) {
1453  case FTP_COMMAND_STOR:
1454  JB_SET_STRING(jb, "command", "STOR");
1455  break;
1456  case FTP_COMMAND_RETR:
1457  JB_SET_STRING(jb, "command", "RETR");
1458  break;
1459  default:
1460  break;
1461  }
1462 }
1463 
1464 /**
1465  * \brief Free memory allocated for global FTP parser state.
1466  */
1468 {
1469  FTPFreeMpmState();
1470 }
1471 
1472 /* UNITTESTS */
1473 #ifdef UNITTESTS
1474 
1475 /** \test Send a get request in one chunk. */
1476 static int FTPParserTest01(void)
1477 {
1478  int result = 1;
1479  Flow f;
1480  uint8_t ftpbuf[] = "PORT 192,168,1,1,0,80\r\n";
1481  uint32_t ftplen = sizeof(ftpbuf) - 1; /* minus the \0 */
1482  TcpSession ssn;
1484 
1485  memset(&f, 0, sizeof(f));
1486  memset(&ssn, 0, sizeof(ssn));
1487 
1488  FLOW_INITIALIZE(&f);
1489  f.protoctx = (void *)&ssn;
1490  f.proto = IPPROTO_TCP;
1491  f.alproto = ALPROTO_FTP;
1492 
1494 
1495  FLOWLOCK_WRLOCK(&f);
1496  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_FTP,
1497  STREAM_TOSERVER | STREAM_EOF, ftpbuf, ftplen);
1498  if (r != 0) {
1499  SCLogDebug("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
1500  result = 0;
1501  FLOWLOCK_UNLOCK(&f);
1502  goto end;
1503  }
1504  FLOWLOCK_UNLOCK(&f);
1505 
1506  FtpState *ftp_state = f.alstate;
1507  if (ftp_state == NULL) {
1508  SCLogDebug("no ftp state: ");
1509  result = 0;
1510  goto end;
1511  }
1512 
1513  if (ftp_state->command != FTP_COMMAND_PORT) {
1514  SCLogDebug("expected command %" PRIu32 ", got %" PRIu32 ": ", FTP_COMMAND_PORT, ftp_state->command);
1515  result = 0;
1516  goto end;
1517  }
1518 
1519 end:
1520  if (alp_tctx != NULL)
1523  FLOW_DESTROY(&f);
1524  return result;
1525 }
1526 
1527 /** \test Send a split get request. */
1528 static int FTPParserTest03(void)
1529 {
1530  int result = 1;
1531  Flow f;
1532  uint8_t ftpbuf1[] = "POR";
1533  uint32_t ftplen1 = sizeof(ftpbuf1) - 1; /* minus the \0 */
1534  uint8_t ftpbuf2[] = "T 192,168,1";
1535  uint32_t ftplen2 = sizeof(ftpbuf2) - 1; /* minus the \0 */
1536  uint8_t ftpbuf3[] = "1,1,10,20\r\n";
1537  uint32_t ftplen3 = sizeof(ftpbuf3) - 1; /* minus the \0 */
1538  TcpSession ssn;
1540 
1541  memset(&f, 0, sizeof(f));
1542  memset(&ssn, 0, sizeof(ssn));
1543 
1544  FLOW_INITIALIZE(&f);
1545  f.protoctx = (void *)&ssn;
1546  f.proto = IPPROTO_TCP;
1547  f.alproto = ALPROTO_FTP;
1548 
1550 
1551  FLOWLOCK_WRLOCK(&f);
1552  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_FTP,
1553  STREAM_TOSERVER | STREAM_START, ftpbuf1,
1554  ftplen1);
1555  if (r != 0) {
1556  SCLogDebug("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
1557  result = 0;
1558  FLOWLOCK_UNLOCK(&f);
1559  goto end;
1560  }
1561  FLOWLOCK_UNLOCK(&f);
1562 
1563  FLOWLOCK_WRLOCK(&f);
1565  ftpbuf2, ftplen2);
1566  if (r != 0) {
1567  SCLogDebug("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
1568  result = 0;
1569  FLOWLOCK_UNLOCK(&f);
1570  goto end;
1571  }
1572  FLOWLOCK_UNLOCK(&f);
1573 
1574  FLOWLOCK_WRLOCK(&f);
1575  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_FTP,
1576  STREAM_TOSERVER | STREAM_EOF, ftpbuf3, ftplen3);
1577  if (r != 0) {
1578  SCLogDebug("toserver chunk 3 returned %" PRId32 ", expected 0: ", r);
1579  result = 0;
1580  FLOWLOCK_UNLOCK(&f);
1581  goto end;
1582  }
1583  FLOWLOCK_UNLOCK(&f);
1584 
1585  FtpState *ftp_state = f.alstate;
1586  if (ftp_state == NULL) {
1587  SCLogDebug("no ftp state: ");
1588  result = 0;
1589  goto end;
1590  }
1591 
1592  if (ftp_state->command != FTP_COMMAND_PORT) {
1593  SCLogDebug("expected command %" PRIu32 ", got %" PRIu32 ": ", FTP_COMMAND_PORT, ftp_state->command);
1594  result = 0;
1595  goto end;
1596  }
1597 
1598 end:
1599  if (alp_tctx != NULL)
1602  return result;
1603 }
1604 
1605 /** \test See how it deals with an incomplete request. */
1606 static int FTPParserTest06(void)
1607 {
1608  int result = 1;
1609  Flow f;
1610  uint8_t ftpbuf1[] = "PORT";
1611  uint32_t ftplen1 = sizeof(ftpbuf1) - 1; /* minus the \0 */
1612  TcpSession ssn;
1614 
1615  memset(&f, 0, sizeof(f));
1616  memset(&ssn, 0, sizeof(ssn));
1617 
1618  FLOW_INITIALIZE(&f);
1619  f.protoctx = (void *)&ssn;
1620  f.proto = IPPROTO_TCP;
1621  f.alproto = ALPROTO_FTP;
1622 
1624 
1625  FLOWLOCK_WRLOCK(&f);
1626  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_FTP,
1628  ftpbuf1,
1629  ftplen1);
1630  if (r != 0) {
1631  SCLogDebug("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
1632  result = 0;
1633  FLOWLOCK_UNLOCK(&f);
1634  goto end;
1635  }
1636  FLOWLOCK_UNLOCK(&f);
1637 
1638  FtpState *ftp_state = f.alstate;
1639  if (ftp_state == NULL) {
1640  SCLogDebug("no ftp state: ");
1641  result = 0;
1642  goto end;
1643  }
1644 
1645  if (ftp_state->command != FTP_COMMAND_UNKNOWN) {
1646  SCLogDebug("expected command %" PRIu32 ", got %" PRIu32 ": ", FTP_COMMAND_UNKNOWN, ftp_state->command);
1647  result = 0;
1648  goto end;
1649  }
1650 
1651 end:
1652  if (alp_tctx != NULL)
1655  FLOW_DESTROY(&f);
1656  return result;
1657 }
1658 
1659 /** \test See how it deals with an incomplete request in multiple chunks. */
1660 static int FTPParserTest07(void)
1661 {
1662  int result = 1;
1663  Flow f;
1664  uint8_t ftpbuf1[] = "PO";
1665  uint32_t ftplen1 = sizeof(ftpbuf1) - 1; /* minus the \0 */
1666  uint8_t ftpbuf2[] = "RT\r\n";
1667  uint32_t ftplen2 = sizeof(ftpbuf2) - 1; /* minus the \0 */
1668  TcpSession ssn;
1670 
1671  memset(&f, 0, sizeof(f));
1672  memset(&ssn, 0, sizeof(ssn));
1673 
1674  FLOW_INITIALIZE(&f);
1675  f.protoctx = (void *)&ssn;
1676  f.proto = IPPROTO_TCP;
1677  f.alproto = ALPROTO_FTP;
1678 
1680 
1681  FLOWLOCK_WRLOCK(&f);
1682  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_FTP,
1683  STREAM_TOSERVER | STREAM_START, ftpbuf1,
1684  ftplen1);
1685  if (r != 0) {
1686  SCLogDebug("toserver chunk 1 returned %" PRId32 ", expected 0: ", r);
1687  result = 0;
1688  FLOWLOCK_UNLOCK(&f);
1689  goto end;
1690  }
1691  FLOWLOCK_UNLOCK(&f);
1692 
1693  FLOWLOCK_WRLOCK(&f);
1694  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_FTP,
1695  STREAM_TOSERVER | STREAM_EOF, ftpbuf2, ftplen2);
1696  if (r != 0) {
1697  SCLogDebug("toserver chunk 2 returned %" PRId32 ", expected 0: ", r);
1698  result = 0;
1699  FLOWLOCK_UNLOCK(&f);
1700  goto end;
1701  }
1702  FLOWLOCK_UNLOCK(&f);
1703 
1704  FtpState *ftp_state = f.alstate;
1705  if (ftp_state == NULL) {
1706  SCLogDebug("no ftp state: ");
1707  result = 0;
1708  goto end;
1709  }
1710 
1711  if (ftp_state->command != FTP_COMMAND_PORT) {
1712  SCLogDebug("expected command %" PRIu32 ", got %" PRIu32 ": ",
1713  FTP_COMMAND_PORT, ftp_state->command);
1714  result = 0;
1715  goto end;
1716  }
1717 
1718 end:
1719  if (alp_tctx != NULL)
1722  FLOW_DESTROY(&f);
1723  return result;
1724 }
1725 
1726 /** \test Test case where chunks are smaller than the delim length and the
1727  * last chunk is supposed to match the delim. */
1728 static int FTPParserTest10(void)
1729 {
1730  int result = 1;
1731  Flow f;
1732  uint8_t ftpbuf1[] = "PORT 1,2,3,4,5,6\r\n";
1733  uint32_t ftplen1 = sizeof(ftpbuf1) - 1; /* minus the \0 */
1734  TcpSession ssn;
1736  int r = 0;
1737  memset(&f, 0, sizeof(f));
1738  memset(&ssn, 0, sizeof(ssn));
1739 
1740  FLOW_INITIALIZE(&f);
1741  f.protoctx = (void *)&ssn;
1742  f.proto = IPPROTO_TCP;
1743  f.alproto = ALPROTO_FTP;
1744 
1746 
1747  uint32_t u;
1748  for (u = 0; u < ftplen1; u++) {
1749  uint8_t flags = 0;
1750 
1751  if (u == 0) flags = STREAM_TOSERVER|STREAM_START;
1752  else if (u == (ftplen1 - 1)) flags = STREAM_TOSERVER|STREAM_EOF;
1753  else flags = STREAM_TOSERVER;
1754 
1755  FLOWLOCK_WRLOCK(&f);
1757  &ftpbuf1[u], 1);
1758  if (r != 0) {
1759  SCLogDebug("toserver chunk %" PRIu32 " returned %" PRId32 ", expected 0: ", u, r);
1760  result = 0;
1761  FLOWLOCK_UNLOCK(&f);
1762  goto end;
1763  }
1764  FLOWLOCK_UNLOCK(&f);
1765  }
1766 
1767  FtpState *ftp_state = f.alstate;
1768  if (ftp_state == NULL) {
1769  SCLogDebug("no ftp state: ");
1770  result = 0;
1771  goto end;
1772  }
1773 
1774  if (ftp_state->command != FTP_COMMAND_PORT) {
1775  SCLogDebug("expected command %" PRIu32 ", got %" PRIu32 ": ", FTP_COMMAND_PORT, ftp_state->command);
1776  result = 0;
1777  goto end;
1778  }
1779 
1780 end:
1781  if (alp_tctx != NULL)
1784  FLOW_DESTROY(&f);
1785  return result;
1786 }
1787 
1788 /** \test Supply RETR without a filename */
1789 static int FTPParserTest11(void)
1790 {
1791  int result = 1;
1792  Flow f;
1793  uint8_t ftpbuf1[] = "PORT 192,168,1,1,0,80\r\n";
1794  uint8_t ftpbuf2[] = "RETR\r\n";
1795  uint8_t ftpbuf3[] = "227 OK\r\n";
1796  TcpSession ssn;
1797 
1799 
1800  memset(&f, 0, sizeof(f));
1801  memset(&ssn, 0, sizeof(ssn));
1802 
1803  FLOW_INITIALIZE(&f);
1804  f.protoctx = (void *)&ssn;
1805  f.proto = IPPROTO_TCP;
1806  f.alproto = ALPROTO_FTP;
1807 
1809 
1810  FLOWLOCK_WRLOCK(&f);
1811  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_FTP,
1812  STREAM_TOSERVER | STREAM_START, ftpbuf1,
1813  sizeof(ftpbuf1) - 1);
1814  if (r != 0) {
1815  result = 0;
1816  FLOWLOCK_UNLOCK(&f);
1817  goto end;
1818  }
1819  FLOWLOCK_UNLOCK(&f);
1820 
1821  /* Response */
1822  FLOWLOCK_WRLOCK(&f);
1823  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_FTP,
1825  ftpbuf3,
1826  sizeof(ftpbuf3) - 1);
1827  if (r != 0) {
1828  result = 0;
1829  FLOWLOCK_UNLOCK(&f);
1830  goto end;
1831  }
1832  FLOWLOCK_UNLOCK(&f);
1833 
1834  FLOWLOCK_WRLOCK(&f);
1835  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_FTP,
1836  STREAM_TOSERVER, ftpbuf2,
1837  sizeof(ftpbuf2) - 1);
1838  if (r == 0) {
1839  SCLogDebug("parse should've failed");
1840  result = 0;
1841  FLOWLOCK_UNLOCK(&f);
1842  goto end;
1843  }
1844  FLOWLOCK_UNLOCK(&f);
1845 
1846  FtpState *ftp_state = f.alstate;
1847  if (ftp_state == NULL) {
1848  SCLogDebug("no ftp state: ");
1849  result = 0;
1850  goto end;
1851  }
1852 
1853  if (ftp_state->command != FTP_COMMAND_RETR) {
1854  SCLogDebug("expected command %" PRIu32 ", got %" PRIu32 ": ",
1855  FTP_COMMAND_RETR, ftp_state->command);
1856  result = 0;
1857  goto end;
1858  }
1859 
1860 end:
1861  if (alp_tctx != NULL)
1864  FLOW_DESTROY(&f);
1865  return result;
1866 }
1867 
1868 /** \test Supply STOR without a filename */
1869 static int FTPParserTest12(void)
1870 {
1871  int result = 1;
1872  Flow f;
1873  uint8_t ftpbuf1[] = "PORT 192,168,1,1,0,80\r\n";
1874  uint8_t ftpbuf2[] = "STOR\r\n";
1875  uint8_t ftpbuf3[] = "227 OK\r\n";
1876  TcpSession ssn;
1877 
1879 
1880  memset(&f, 0, sizeof(f));
1881  memset(&ssn, 0, sizeof(ssn));
1882 
1883  FLOW_INITIALIZE(&f);
1884  f.protoctx = (void *)&ssn;
1885  f.proto = IPPROTO_TCP;
1886  f.alproto = ALPROTO_FTP;
1887 
1889 
1890  FLOWLOCK_WRLOCK(&f);
1891  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_FTP,
1892  STREAM_TOSERVER | STREAM_START, ftpbuf1,
1893  sizeof(ftpbuf1) - 1);
1894  if (r != 0) {
1895  result = 0;
1896  FLOWLOCK_UNLOCK(&f);
1897  goto end;
1898  }
1899  FLOWLOCK_UNLOCK(&f);
1900 
1901  /* Response */
1902  FLOWLOCK_WRLOCK(&f);
1903  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_FTP,
1905  ftpbuf3,
1906  sizeof(ftpbuf3) - 1);
1907  if (r != 0) {
1908  result = 0;
1909  FLOWLOCK_UNLOCK(&f);
1910  goto end;
1911  }
1912  FLOWLOCK_UNLOCK(&f);
1913 
1914  FLOWLOCK_WRLOCK(&f);
1915  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_FTP,
1916  STREAM_TOSERVER, ftpbuf2,
1917  sizeof(ftpbuf2) - 1);
1918  if (r == 0) {
1919  SCLogDebug("parse should've failed");
1920  result = 0;
1921  FLOWLOCK_UNLOCK(&f);
1922  goto end;
1923  }
1924  FLOWLOCK_UNLOCK(&f);
1925 
1926  FtpState *ftp_state = f.alstate;
1927  if (ftp_state == NULL) {
1928  SCLogDebug("no ftp state: ");
1929  result = 0;
1930  goto end;
1931  }
1932 
1933  if (ftp_state->command != FTP_COMMAND_STOR) {
1934  SCLogDebug("expected command %" PRIu32 ", got %" PRIu32 ": ",
1935  FTP_COMMAND_STOR, ftp_state->command);
1936  result = 0;
1937  goto end;
1938  }
1939 
1940 end:
1941  if (alp_tctx != NULL)
1944  FLOW_DESTROY(&f);
1945  return result;
1946 }
1947 #endif /* UNITTESTS */
1948 
1950 {
1951 #ifdef UNITTESTS
1952  UtRegisterTest("FTPParserTest01", FTPParserTest01);
1953  UtRegisterTest("FTPParserTest03", FTPParserTest03);
1954  UtRegisterTest("FTPParserTest06", FTPParserTest06);
1955  UtRegisterTest("FTPParserTest07", FTPParserTest07);
1956  UtRegisterTest("FTPParserTest10", FTPParserTest10);
1957  UtRegisterTest("FTPParserTest11", FTPParserTest11);
1958  UtRegisterTest("FTPParserTest12", FTPParserTest12);
1959 #endif /* UNITTESTS */
1960 }
1961 
MpmInitThreadCtx
void MpmInitThreadCtx(MpmThreadCtx *mpm_thread_ctx, uint16_t matcher)
Definition: util-mpm.c:259
FtpLineState_::current_line_lf_seen
uint8_t current_line_lf_seen
Definition: app-layer-ftp.h:125
AppLayerParserRegisterGetStateProgressFunc
void AppLayerParserRegisterGetStateProgressFunc(uint8_t ipproto, AppProto alproto, int(*StateGetProgress)(void *alstate, uint8_t direction))
Definition: app-layer-parser.c:490
FTPTransaction_::command_descriptor
const FtpCommand * command_descriptor
Definition: app-layer-ftp.h:149
FileContainer_
Definition: util-file.h:100
len
uint8_t len
Definition: app-layer-dnp3.h:2
FTP_COMMAND_USER
@ FTP_COMMAND_USER
Definition: app-layer-ftp.h:84
FTP_COMMAND_STAT
@ FTP_COMMAND_STAT
Definition: app-layer-ftp.h:77
FTP_COMMAND_DELE
@ FTP_COMMAND_DELE
Definition: app-layer-ftp.h:46
FTPTransaction_::request
uint8_t * request
Definition: app-layer-ftp.h:146
StreamingBufferConfig_::Malloc
void *(* Malloc)(size_t size)
Definition: util-streaming-buffer.h:71
AppLayerProtoDetectPMRegisterPatternCI
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.
Definition: app-layer-detect-proto.c:1750
FTPThreadCtx_
Definition: app-layer-ftp.c:64
FtpTransferCmd::flow_id
uint64_t flow_id
Definition: app-layer-ftp.c:503
StreamingBufferConfig_::buf_size
uint32_t buf_size
Definition: util-streaming-buffer.h:70
AppLayerParserRegisterLocalStorageFunc
void AppLayerParserRegisterLocalStorageFunc(uint8_t ipproto, AppProto alproto, void *(*LocalStorageAlloc)(void), void(*LocalStorageFree)(void *))
Definition: app-layer-parser.c:411
FTP_COMMAND_ALLO
@ FTP_COMMAND_ALLO
Definition: app-layer-ftp.h:40
TAILQ_INIT
#define TAILQ_INIT(head)
Definition: queue.h:370
FtpDataState_::detect_flags_ts
uint64_t detect_flags_ts
Definition: app-layer-ftp.h:214
FtpState_::active
bool active
Definition: app-layer-ftp.h:170
flow-util.h
SC_ATOMIC_INIT
#define SC_ATOMIC_INIT(name)
wrapper for initializing an atomic variable.
Definition: util-atomic.h:286
FtpCommands
const FtpCommand FtpCommands[FTP_COMMAND_MAX+1]
Definition: app-layer-ftp.c:73
FileContainerAlloc
FileContainer * FileContainerAlloc(void)
allocate a FileContainer
Definition: util-file.c:423
FtpDataState_::state
uint8_t state
Definition: app-layer-ftp.h:212
AppLayerParserRegisterStateFuncs
void AppLayerParserRegisterStateFuncs(uint8_t ipproto, AppProto alproto, void *(*StateAlloc)(void), void(*StateFree)(void *))
Definition: app-layer-parser.c:397
StreamingBufferConfig_::Calloc
void *(* Calloc)(size_t n, size_t size)
Definition: util-streaming-buffer.h:72
DetectEngineState_
Definition: detect-engine-state.h:92
MpmThreadCtx_
Definition: util-mpm.h:46
FtpState_::input_len
int32_t input_len
Definition: app-layer-ftp.h:168
stream-tcp.h
FtpState
struct FtpState_ FtpState
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:103
FTPString_::len
uint16_t len
Definition: app-layer-ftp.h:130
PrefilterRuleStore_
structure for storing potential rule matches
Definition: util-prefilter.h:32
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:298
ParseSizeStringU64
int ParseSizeStringU64(const char *size, uint64_t *res)
Definition: util-misc.c:203
next
struct HtpBodyChunk_ * next
Definition: app-layer-htp.h:0
AppLayerParserRegisterDetectFlagsFuncs
void AppLayerParserRegisterDetectFlagsFuncs(uint8_t ipproto, AppProto alproto, uint64_t(*GetTxDetectFlags)(void *tx, uint8_t dir), void(*SetTxDetectFlags)(void *tx, uint8_t dir, uint64_t))
Definition: app-layer-parser.c:589
FtpDataState_::detect_flags_tc
uint64_t detect_flags_tc
Definition: app-layer-ftp.h:215
FtpLineState_::db_len
uint32_t db_len
Definition: app-layer-ftp.h:122
MpmInitCtx
void MpmInitCtx(MpmCtx *mpm_ctx, uint16_t matcher)
Definition: util-mpm.c:264
FTP_COMMAND_RNFR
@ FTP_COMMAND_RNFR
Definition: app-layer-ftp.h:72
AppLayerParserRegisterLoggerFuncs
void AppLayerParserRegisterLoggerFuncs(uint8_t ipproto, AppProto alproto, LoggerId(*StateGetTxLogged)(void *, void *), void(*StateSetTxLogged)(void *, void *, LoggerId))
Definition: app-layer-parser.c:447
Flow_::proto
uint8_t proto
Definition: flow.h:361
FtpState_::command
FtpRequestCommand command
Definition: app-layer-ftp.h:186
AppLayerParserConfParserEnabled
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
Definition: app-layer-parser.c:302
FTP_STATE_PORT_DONE
@ FTP_STATE_PORT_DONE
Definition: app-layer-ftp.h:32
STREAMING_BUFFER_CONFIG_INITIALIZER
#define STREAMING_BUFFER_CONFIG_INITIALIZER
Definition: util-streaming-buffer.h:77
FtpLineState_::current_line_db
uint8_t current_line_db
Definition: app-layer-ftp.h:123
threads.h
Flow_
Flow data structure.
Definition: flow.h:343
FTPTransaction_::done
bool done
Definition: app-layer-ftp.h:152
LoggerId
LoggerId
Definition: suricata-common.h:439
FTP_COMMAND_MSND
@ FTP_COMMAND_MSND
Definition: app-layer-ftp.h:59
FTP_COMMAND_EPSV
@ FTP_COMMAND_EPSV
Definition: app-layer-ftp.h:47
logged
int logged
Definition: app-layer-htp.h:1
SC_ATOMIC_ADD
#define SC_ATOMIC_ADD(name, val)
add a value to our atomic variable
Definition: util-atomic.h:304
AppLayerParserRegisterParserAcceptableDataDirection
void AppLayerParserRegisterParserAcceptableDataDirection(uint8_t ipproto, AppProto alproto, uint8_t direction)
Definition: app-layer-parser.c:376
FTP_COMMAND_RNTO
@ FTP_COMMAND_RNTO
Definition: app-layer-ftp.h:73
FtpState_::line_state
FtpLineState line_state[2]
Definition: app-layer-ftp.h:184
AppLayerParserRegisterTxFreeFunc
void AppLayerParserRegisterTxFreeFunc(uint8_t ipproto, AppProto alproto, void(*StateTransactionFree)(void *, uint64_t))
Definition: app-layer-parser.c:501
FTP_COMMAND_MODE
@ FTP_COMMAND_MODE
Definition: app-layer-ftp.h:55
TAILQ_FOREACH
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:350
FTP_COMMAND_RMD
@ FTP_COMMAND_RMD
Definition: app-layer-ftp.h:71
FtpDataState_::command
FtpRequestCommand command
Definition: app-layer-ftp.h:211
FTPMemuseGlobalCounter
uint64_t FTPMemuseGlobalCounter(void)
Definition: app-layer-ftp.c:169
AppLayerParserThreadCtxFree
void AppLayerParserThreadCtxFree(AppLayerParserThreadCtx *tctx)
Destroys the app layer parser thread context obtained using AppLayerParserThreadCtxAlloc().
Definition: app-layer-parser.c:279
FTP_COMMAND_ABOR
@ FTP_COMMAND_ABOR
Definition: app-layer-ftp.h:38
SCMutexLock
#define SCMutexLock(mut)
Definition: threads-debug.h:117
rust.h
FTP_COMMAND_MKD
@ FTP_COMMAND_MKD
Definition: app-layer-ftp.h:53
FtpCommand_::command
FtpRequestCommand command
Definition: app-layer-ftp.h:93
ALPROTO_FTP
@ ALPROTO_FTP
Definition: app-layer-protos.h:31
stream-tcp-reassemble.h
AppLayerParserRegisterDetectStateFuncs
void AppLayerParserRegisterDetectStateFuncs(uint8_t ipproto, AppProto alproto, DetectEngineState *(*GetTxDetectState)(void *tx), int(*SetTxDetectState)(void *tx, DetectEngineState *))
Definition: app-layer-parser.c:577
FTP_COMMAND_LIST
@ FTP_COMMAND_LIST
Definition: app-layer-ftp.h:50
SCMUTEX_INITIALIZER
#define SCMUTEX_INITIALIZER
Definition: threads-debug.h:121
FtpCommand_::command_name
const char * command_name
Definition: app-layer-ftp.h:94
FtpDataState_::file_len
int16_t file_len
Definition: app-layer-ftp.h:210
TAILQ_INSERT_TAIL
#define TAILQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:385
AppLayerExpectationGetDataId
int AppLayerExpectationGetDataId(void)
Definition: app-layer-expectation.c:287
app-layer-ftp.h
Flow_::protoctx
void * protoctx
Definition: flow.h:416
FileAppendData
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...
Definition: util-file.c:707
FtpDataState_::direction
uint8_t direction
Definition: app-layer-ftp.h:213
util-unittest.h
FtpTransferCmd::file_len
uint16_t file_len
Definition: app-layer-ftp.c:505
FtpState_::direction
uint8_t direction
Definition: app-layer-ftp.h:169
SC_ATOMIC_DECLARE
SC_ATOMIC_DECLARE(uint64_t, ftp_memuse)
FTPParserCleanup
void FTPParserCleanup(void)
Free memory allocated for global FTP parser state.
Definition: app-layer-ftp.c:1467
FLOWLOCK_UNLOCK
#define FLOWLOCK_UNLOCK(fb)
Definition: flow.h:260
STREAM_START
#define STREAM_START
Definition: stream.h:29
FTP_COMMAND_HELP
@ FTP_COMMAND_HELP
Definition: app-layer-ftp.h:48
FTPDATA_STATE_IN_PROGRESS
@ FTPDATA_STATE_IN_PROGRESS
Definition: app-layer-ftp.h:199
FTP_COMMAND_SIZE
@ FTP_COMMAND_SIZE
Definition: app-layer-ftp.h:75
util-memcmp.h
FTPDATA_STATE_FINISHED
@ FTPDATA_STATE_FINISHED
Definition: app-layer-ftp.h:200
SC_ERR_SIZE_PARSE
@ SC_ERR_SIZE_PARSE
Definition: util-error.h:230
ConfGet
int ConfGet(const char *name, const char **vptr)
Retrieve the value of a configuration node.
Definition: conf.c:331
FTP_COMMAND_CWD
@ FTP_COMMAND_CWD
Definition: app-layer-ftp.h:45
FTP_COMMAND_MSAM
@ FTP_COMMAND_MSAM
Definition: app-layer-ftp.h:58
FTP_COMMAND_SITE
@ FTP_COMMAND_SITE
Definition: app-layer-ftp.h:74
FtpState_
Definition: app-layer-ftp.h:166
app-layer-expectation.h
FLOW_INITIALIZE
#define FLOW_INITIALIZE(f)
Definition: flow-util.h:39
AppLayerParserStateIssetFlag
int AppLayerParserStateIssetFlag(AppLayerParserState *pstate, uint8_t flag)
Definition: app-layer-parser.c:1609
FTP_COMMAND_STOU
@ FTP_COMMAND_STOU
Definition: app-layer-ftp.h:79
TAILQ_REMOVE
#define TAILQ_REMOVE(head, elm, field)
Definition: queue.h:412
decode.h
util-debug.h
JB_SET_STRING
#define JB_SET_STRING(jb, key, val)
Definition: rust.h:24
TAILQ_FIRST
#define TAILQ_FIRST(head)
Definition: queue.h:339
FtpState_::port_line
uint8_t * port_line
Definition: app-layer-ftp.h:190
AppLayerParserState_
Definition: app-layer-parser.c:155
FTP_COMMAND_APPE
@ FTP_COMMAND_APPE
Definition: app-layer-ftp.h:41
FTPThreadCtx_::pmq
PrefilterRuleStore * pmq
Definition: app-layer-ftp.c:66
FileFlowToFlags
uint16_t FileFlowToFlags(const Flow *flow, uint8_t direction)
Definition: util-file.c:231
output-json.h
FtpState_::curr_tx
FTPTransaction * curr_tx
Definition: app-layer-ftp.h:172
FTP_COMMAND_TYPE
@ FTP_COMMAND_TYPE
Definition: app-layer-ftp.h:82
SCMutexUnlock
#define SCMutexUnlock(mut)
Definition: threads-debug.h:119
STREAM_TOSERVER
#define STREAM_TOSERVER
Definition: stream.h:31
alp_tctx
AppLayerParserThreadCtx * alp_tctx
Definition: fuzz_applayerparserparse.c:19
FLOWLOCK_WRLOCK
#define FLOWLOCK_WRLOCK(fb)
Definition: flow.h:257
AppLayerParserRegisterGetFilesFunc
void AppLayerParserRegisterGetFilesFunc(uint8_t ipproto, AppProto alproto, FileContainer *(*StateGetFiles)(void *, uint8_t))
Definition: app-layer-parser.c:425
util-print.h
SCEnter
#define SCEnter(...)
Definition: util-debug.h:300
FTP_COMMAND_PORT
@ FTP_COMMAND_PORT
Definition: app-layer-ftp.h:65
FTP_COMMAND_MAX
@ FTP_COMMAND_MAX
Definition: app-layer-ftp.h:88
FTP_COMMAND_REIN
@ FTP_COMMAND_REIN
Definition: app-layer-ftp.h:68
FtpTransferCmd::cmd
FtpRequestCommand cmd
Definition: app-layer-ftp.c:506
app-layer-parser.h
TRUE
#define TRUE
Definition: suricata-common.h:33
FtpState_::input
const uint8_t * input
Definition: app-layer-ftp.h:167
FTP_STATE_FINISHED
@ FTP_STATE_FINISHED
Definition: app-layer-ftp.h:33
PmqReset
void PmqReset(PrefilterRuleStore *)
Reset a Pmq for reusage. Meant to be called after a single search.
Definition: util-prefilter.c:101
SC_ATOMIC_SUB
#define SC_ATOMIC_SUB(name, val)
sub a value from our atomic variable
Definition: util-atomic.h:313
FTPParserRegisterTests
void FTPParserRegisterTests(void)
Definition: app-layer-ftp.c:1949
RegisterFTPParsers
void RegisterFTPParsers(void)
Definition: app-layer-ftp.c:1317
stream.h
AppLayerParserRegisterProtocolUnittests
void AppLayerParserRegisterProtocolUnittests(uint8_t ipproto, AppProto alproto, void(*RegisterUnittests)(void))
Definition: app-layer-parser.c:1707
AppLayerExpectationCreate
int AppLayerExpectationCreate(Flow *f, int direction, Port src, Port dst, AppProto alproto, void *data)
Definition: app-layer-expectation.c:218
FtpCommand_
Definition: app-layer-ftp.h:92
StreamTcpFreeConfig
void StreamTcpFreeConfig(char quiet)
Definition: stream-tcp.c:669
FtpTransferCmd
Definition: app-layer-ftp.c:499
stream-tcp-private.h
ftp_config_memcap
uint64_t ftp_config_memcap
Definition: app-layer-ftp.c:127
FTP_COMMAND_CHMOD
@ FTP_COMMAND_CHMOD
Definition: app-layer-ftp.h:44
AppLayerRegisterExpectationProto
void AppLayerRegisterExpectationProto(uint8_t proto, AppProto alproto)
Definition: app-layer-detect-proto.c:2097
MpmTableElmt_::Prepare
int(* Prepare)(struct MpmCtx_ *)
Definition: util-mpm.h:161
FTP_COMMAND_SYST
@ FTP_COMMAND_SYST
Definition: app-layer-ftp.h:81
FileOpenFileWithId
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.
Definition: util-file.c:918
SCReturnPtr
#define SCReturnPtr(x, type)
Definition: util-debug.h:316
detect-engine-state.h
Data structures and function prototypes for keeping state for the detection engine.
AppLayerProtoDetectRegisterProtocol
void AppLayerProtoDetectRegisterProtocol(AppProto alproto, const char *alproto_name)
Registers a protocol for protocol detection phase.
Definition: app-layer-detect-proto.c:1826
FtpDataState
struct FtpDataState_ FtpDataState
APP_LAYER_PARSER_EOF
#define APP_LAYER_PARSER_EOF
Definition: app-layer-parser.h:35
FTP_COMMAND_ACCT
@ FTP_COMMAND_ACCT
Definition: app-layer-ftp.h:39
FTPMemcapGlobalCounter
uint64_t FTPMemcapGlobalCounter(void)
Definition: app-layer-ftp.c:175
MpmTableElmt_::Search
uint32_t(* Search)(const struct MpmCtx_ *, struct MpmThreadCtx_ *, PrefilterRuleStore *, const uint8_t *, uint32_t)
Definition: util-mpm.h:162
FTP_COMMAND_MRSQ
@ FTP_COMMAND_MRSQ
Definition: app-layer-ftp.h:57
SCLogInfo
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:217
AppLayerParserRegisterParser
int AppLayerParserRegisterParser(uint8_t ipproto, AppProto alproto, uint8_t direction, AppLayerParserFPtr Parser)
Register app layer parser for the protocol.
Definition: app-layer-parser.c:364
DetectEngineStateFree
void DetectEngineStateFree(DetectEngineState *state)
Frees a DetectEngineState object.
Definition: detect-engine-state.c:175
AppLayerParserRegisterGetStateProgressCompletionStatus
void AppLayerParserRegisterGetStateProgressCompletionStatus(AppProto alproto, int(*StateGetProgressCompletionStatus)(uint8_t direction))
Definition: app-layer-parser.c:542
SCRealloc
#define SCRealloc(ptr, sz)
Definition: util-mem.h:50
AppLayerParserThreadCtxAlloc
AppLayerParserThreadCtx * AppLayerParserThreadCtxAlloc(void)
Gets a new app layer protocol's parser thread context.
Definition: app-layer-parser.c:253
AppLayerParserRegisterGetTx
void AppLayerParserRegisterGetTx(uint8_t ipproto, AppProto alproto, void *(StateGetTx)(void *alstate, uint64_t tx_id))
Definition: app-layer-parser.c:523
FtpState_::current_line
const uint8_t * current_line
Definition: app-layer-ftp.h:178
util-mem.h
length
uint16_t length
Definition: app-layer-modbus.c:2
APP_LAYER_OK
#define APP_LAYER_OK
Definition: app-layer-parser.h:56
flow-storage.h
AppLayerRequestProtocolTLSUpgrade
void AppLayerRequestProtocolTLSUpgrade(Flow *f)
request applayer to wrap up this protocol and rerun protocol detection with expectation of TLS....
Definition: app-layer-detect-proto.c:1865
SCReturnStruct
#define SCReturnStruct(x)
Definition: util-debug.h:320
FTPTransaction_::request_length
uint32_t request_length
Definition: app-layer-ftp.h:145
util-mpm.h
flags
uint8_t flags
Definition: decode-gre.h:0
FTP_COMMAND_NOOP
@ FTP_COMMAND_NOOP
Definition: app-layer-ftp.h:62
AppLayerParserParse
int AppLayerParserParse(ThreadVars *tv, AppLayerParserThreadCtx *alp_tctx, Flow *f, AppProto alproto, uint8_t flags, const uint8_t *input, uint32_t input_len)
Definition: app-layer-parser.c:1171
FtpLineState_
Definition: app-layer-ftp.h:118
FTP_COMMAND_CDUP
@ FTP_COMMAND_CDUP
Definition: app-layer-ftp.h:43
suricata-common.h
FTP_COMMAND_PASS
@ FTP_COMMAND_PASS
Definition: app-layer-ftp.h:63
FtpState_::current_line_len
uint32_t current_line_len
Definition: app-layer-ftp.h:180
FTPTransaction_::de_state
DetectEngineState * de_state
Definition: app-layer-ftp.h:160
FtpState_::port_line_len
uint32_t port_line_len
Definition: app-layer-ftp.h:188
FtpState_::dyn_port
uint16_t dyn_port
Definition: app-layer-ftp.h:192
util-spm.h
STREAM_TOCLIENT
#define STREAM_TOCLIENT
Definition: stream.h:32
PmqFree
void PmqFree(PrefilterRuleStore *)
Cleanup and free a Pmq.
Definition: util-prefilter.c:126
SCLogError
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:257
ALPROTO_FTPDATA
@ ALPROTO_FTPDATA
Definition: app-layer-protos.h:47
FtpTransferCmd::DFree
void(* DFree)(void *)
Definition: app-layer-ftp.c:502
FTPAtExitPrintStats
void FTPAtExitPrintStats(void)
Definition: app-layer-ftp.c:1403
Flow_::parent_id
int64_t parent_id
Definition: flow.h:405
FTP_COMMAND_MRCP
@ FTP_COMMAND_MRCP
Definition: app-layer-ftp.h:56
FtpDataState_
Definition: app-layer-ftp.h:204
FTP_COMMAND_PWD
@ FTP_COMMAND_PWD
Definition: app-layer-ftp.h:66
FTP_COMMAND_STRU
@ FTP_COMMAND_STRU
Definition: app-layer-ftp.h:80
StreamingBufferConfig_
Definition: util-streaming-buffer.h:67
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
FTP_COMMAND_UNKNOWN
@ FTP_COMMAND_UNKNOWN
Definition: app-layer-ftp.h:37
FTP_COMMAND_MAIL
@ FTP_COMMAND_MAIL
Definition: app-layer-ftp.h:51
FTP_COMMAND_UMASK
@ FTP_COMMAND_UMASK
Definition: app-layer-ftp.h:83
str
#define str(s)
Definition: suricata-common.h:273
MpmTableElmt_::DestroyCtx
void(* DestroyCtx)(struct MpmCtx_ *)
Definition: util-mpm.h:145
SCFree
#define SCFree(p)
Definition: util-mem.h:61
Flow_::alstate
void * alstate
Definition: flow.h:454
FTPTransaction_::detect_flags_tc
uint64_t detect_flags_tc
Definition: app-layer-ftp.h:139
PmqSetup
int PmqSetup(PrefilterRuleStore *)
Setup a pmq.
Definition: util-prefilter.c:36
StreamingBufferConfig_::Free
void(* Free)(void *ptr, size_t size)
Definition: util-streaming-buffer.h:74
src
uint16_t src
Definition: app-layer-dnp3.h:5
FTPTransaction_::logged
uint32_t logged
Definition: app-layer-ftp.h:142
FtpState_::tx_cnt
uint64_t tx_cnt
Definition: app-layer-ftp.h:174
EveFTPDataAddMetadata
void EveFTPDataAddMetadata(const Flow *f, JsonBuilder *jb)
Definition: app-layer-ftp.c:1441
StreamTcpInitConfig
void StreamTcpInitConfig(char)
To initialize the stream global configuration data.
Definition: stream-tcp.c:365
FtpDataState_::de_state
DetectEngineState * de_state
Definition: app-layer-ftp.h:208
STREAM_EOF
#define STREAM_EOF
Definition: stream.h:30
FlowGetStorageById
void * FlowGetStorageById(Flow *f, int id)
Definition: flow-storage.c:39
mpm_table
MpmTableElmt mpm_table[MPM_TABLE_SIZE]
Definition: util-mpm.c:48
app-layer-protos.h
FTP_COMMAND_IDLE
@ FTP_COMMAND_IDLE
Definition: app-layer-ftp.h:49
AppLayerParserRegisterGetTxCnt
void AppLayerParserRegisterGetTxCnt(uint8_t ipproto, AppProto alproto, uint64_t(*StateGetTxCnt)(void *alstate))
Definition: app-layer-parser.c:512
APP_LAYER_ERROR
#define APP_LAYER_ERROR
Definition: app-layer-parser.h:60
FtpState_::port_line_size
uint32_t port_line_size
Definition: app-layer-ftp.h:189
FTP_COMMAND_RETR
@ FTP_COMMAND_RETR
Definition: app-layer-ftp.h:70
FTP_MPM
#define FTP_MPM
Definition: app-layer-ftp.c:69
FTPTransaction_::tx_id
uint64_t tx_id
Definition: app-layer-ftp.h:136
FTPTransaction_::dyn_port
uint16_t dyn_port
Definition: app-layer-ftp.h:151
FTPTransaction_::active
bool active
Definition: app-layer-ftp.h:153
FILE_USE_DETECT
#define FILE_USE_DETECT
Definition: util-file.h:49
FTP_COMMAND_STOR
@ FTP_COMMAND_STOR
Definition: app-layer-ftp.h:78
FtpDataState_::files
FileContainer * files
Definition: app-layer-ftp.h:207
likely
#define likely(expr)
Definition: util-optimize.h:32
FTP_COMMAND_MSOM
@ FTP_COMMAND_MSOM
Definition: app-layer-ftp.h:60
MpmTableElmt_::DestroyThreadCtx
void(* DestroyThreadCtx)(struct MpmCtx_ *, struct MpmThreadCtx_ *)
Definition: util-mpm.h:146
AppLayerParserThreadCtx_
Definition: app-layer-parser.c:85
FTP_COMMAND_EPRT
@ FTP_COMMAND_EPRT
Definition: app-layer-ftp.h:85
FileContainerFree
void FileContainerFree(FileContainer *ffc)
Free a FileContainer.
Definition: util-file.c:459
FTPString_
Definition: app-layer-ftp.h:128
SC_ATOMIC_GET
#define SC_ATOMIC_GET(name)
Get the value from the atomic variable.
Definition: util-atomic.h:347
FtpLineState_::db
uint8_t * db
Definition: app-layer-ftp.h:121
MpmCtx_
Definition: util-mpm.h:88
TcpSession_
Definition: stream-tcp-private.h:260
JsonGetNextLineFromBuffer
uint16_t JsonGetNextLineFromBuffer(const char *buffer, const uint16_t len)
Definition: app-layer-ftp.c:1431
util-misc.h
FtpRequestCommand
FtpRequestCommand
Definition: app-layer-ftp.h:36
FTPTransaction_
Definition: app-layer-ftp.h:134
FTPThreadCtx
struct FTPThreadCtx_ FTPThreadCtx
Flow_::alproto
AppProto alproto
application level protocol
Definition: flow.h:425
FlowFreeStorageById
void FlowFreeStorageById(Flow *f, int id)
Definition: flow-storage.c:54
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
FTP_COMMAND_REST
@ FTP_COMMAND_REST
Definition: app-layer-ftp.h:69
util-pool.h
FTP_STATE_IN_PROGRESS
@ FTP_STATE_IN_PROGRESS
Definition: app-layer-ftp.h:31
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:304
FtpState_::current_line_delimiter_len
uint8_t current_line_delimiter_len
Definition: app-layer-ftp.h:181
MpmAddPatternCI
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)
Definition: util-mpm.c:314
SCMemcmp
#define SCMemcmp(a, b, c)
Definition: util-memcmp.h:369
FTP_COMMAND_PASV
@ FTP_COMMAND_PASV
Definition: app-layer-ftp.h:64
AppLayerProtoDetectConfProtoDetectionEnabled
int AppLayerProtoDetectConfProtoDetectionEnabled(const char *ipproto, const char *alproto)
Given a protocol name, checks if proto detection is enabled in the conf file.
Definition: app-layer-detect-proto.c:1890
FileCloseFile
int FileCloseFile(FileContainer *ffc, const uint8_t *data, uint32_t data_len, uint16_t flags)
Close a File.
Definition: util-file.c:1012
FTP_COMMAND_AUTH_TLS
@ FTP_COMMAND_AUTH_TLS
Definition: app-layer-ftp.h:42
util-memrchr.h
SCMutex
#define SCMutex
Definition: threads-debug.h:114
FTPString_::str
uint8_t * str
Definition: app-layer-ftp.h:129
FTPThreadCtx_::ftp_mpm_thread_ctx
MpmThreadCtx * ftp_mpm_thread_ctx
Definition: app-layer-ftp.c:65
FLOW_DESTROY
#define FLOW_DESTROY(f)
Definition: flow-util.h:121
FTP_COMMAND_NLST
@ FTP_COMMAND_NLST
Definition: app-layer-ftp.h:61
FTP_COMMAND_MDTM
@ FTP_COMMAND_MDTM
Definition: app-layer-ftp.h:52
FTP_COMMAND_SMNT
@ FTP_COMMAND_SMNT
Definition: app-layer-ftp.h:76
FTP_COMMAND_QUIT
@ FTP_COMMAND_QUIT
Definition: app-layer-ftp.h:67
debug.h
StreamingBufferConfig_::Realloc
void *(* Realloc)(void *ptr, size_t orig_size, size_t size)
Definition: util-streaming-buffer.h:73
FtpDataState_::file_name
uint8_t * file_name
Definition: app-layer-ftp.h:206
FTPTransaction_::detect_flags_ts
uint64_t detect_flags_ts
Definition: app-layer-ftp.h:138
FTP_COMMAND_MLFL
@ FTP_COMMAND_MLFL
Definition: app-layer-ftp.h:54
FtpTransferCmd::file_name
uint8_t * file_name
Definition: app-layer-ftp.c:504
app-layer.h
PrefilterRuleStore_::rule_id_array
SigIntId * rule_id_array
Definition: util-prefilter.h:36