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