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 *, FTPTransaction *);
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  if (FTPCheckMemcap((uint32_t)(n * size)) == 0)
215  return NULL;
216 
217  void *ptr = SCCalloc(n, size);
218 
219  if (unlikely(ptr == NULL))
220  return NULL;
221 
222  FTPIncrMemuse((uint64_t)(n * size));
223  return ptr;
224 }
225 
226 static void *FTPRealloc(void *ptr, size_t orig_size, size_t size)
227 {
228  void *rptr = NULL;
229 
230  if (FTPCheckMemcap((uint32_t)(size - orig_size)) == 0)
231  return NULL;
232 
233  rptr = SCRealloc(ptr, size);
234  if (rptr == NULL)
235  return NULL;
236 
237  if (size > orig_size) {
238  FTPIncrMemuse(size - orig_size);
239  } else {
240  FTPDecrMemuse(orig_size - size);
241  }
242 
243  return rptr;
244 }
245 
246 static void FTPFree(void *ptr, size_t size)
247 {
248  SCFree(ptr);
249 
250  FTPDecrMemuse((uint64_t)size);
251 }
252 
253 static FTPString *FTPStringAlloc(void)
254 {
255  return FTPCalloc(1, sizeof(FTPString));
256 }
257 
258 static void FTPStringFree(FTPString *str)
259 {
260  if (str->str) {
261  FTPFree(str->str, str->len);
262  }
263 
264  FTPFree(str, sizeof(FTPString));
265 }
266 
267 static void *FTPLocalStorageAlloc(void)
268 {
269  /* needed by the mpm */
270  FTPThreadCtx *td = SCCalloc(1, sizeof(*td));
271  if (td == NULL) {
272  exit(EXIT_FAILURE);
273  }
274 
275  td->pmq = SCCalloc(1, sizeof(*td->pmq));
276  if (td->pmq == NULL) {
277  exit(EXIT_FAILURE);
278  }
279  PmqSetup(td->pmq);
280 
281  td->ftp_mpm_thread_ctx = SCCalloc(1, sizeof(MpmThreadCtx));
282  if (unlikely(td->ftp_mpm_thread_ctx == NULL)) {
283  exit(EXIT_FAILURE);
284  }
286  return td;
287 }
288 
289 static void FTPLocalStorageFree(void *ptr)
290 {
291  FTPThreadCtx *td = ptr;
292  if (td != NULL) {
293  if (td->pmq != NULL) {
294  PmqFree(td->pmq);
295  SCFree(td->pmq);
296  }
297 
298  if (td->ftp_mpm_thread_ctx != NULL) {
301  }
302 
303  SCFree(td);
304  }
305 
306  return;
307 }
308 static FTPTransaction *FTPTransactionCreate(FtpState *state)
309 {
310  SCEnter();
311  FTPTransaction *tx = FTPCalloc(1, sizeof(*tx));
312  if (tx == NULL) {
313  return NULL;
314  }
315 
316  TAILQ_INSERT_TAIL(&state->tx_list, tx, next);
317  tx->tx_id = state->tx_cnt++;
318 
319  TAILQ_INIT(&tx->response_list);
320 
321  SCLogDebug("new transaction %p (state tx cnt %"PRIu64")", tx, state->tx_cnt);
322  return tx;
323 }
324 
325 static void FTPTransactionFree(FTPTransaction *tx)
326 {
327  SCEnter();
328 
329  if (tx->de_state != NULL) {
331  }
332 
333  if (tx->request) {
334  FTPFree(tx->request, tx->request_length);
335  }
336 
337  FTPString *str = NULL;
338  while ((str = TAILQ_FIRST(&tx->response_list))) {
339  TAILQ_REMOVE(&tx->response_list, str, next);
340  FTPStringFree(str);
341  }
342 
343  FTPFree(tx, sizeof(*tx));
344 }
345 
346 static int FTPGetLineForDirection(FtpState *state, FtpLineState *line_state)
347 {
348  void *ptmp;
349  if (line_state->current_line_lf_seen == 1) {
350  /* we have seen the lf for the previous line. Clear the parser
351  * details to parse new line */
352  line_state->current_line_lf_seen = 0;
353  if (line_state->current_line_db == 1) {
354  line_state->current_line_db = 0;
355  FTPFree(line_state->db, line_state->db_len);
356  line_state->db = NULL;
357  line_state->db_len = 0;
358  state->current_line = NULL;
359  state->current_line_len = 0;
360  }
361  }
362 
363  uint8_t *lf_idx = memchr(state->input, 0x0a, state->input_len);
364 
365  if (lf_idx == NULL) {
366  /* fragmented lines. Decoder event for special cases. Not all
367  * fragmented lines should be treated as a possible evasion
368  * attempt. With multi payload ftp chunks we can have valid
369  * cases of fragmentation. But within the same segment chunk
370  * if we see fragmentation then it's definitely something you
371  * should alert about */
372  if (line_state->current_line_db == 0) {
373  line_state->db = FTPMalloc(state->input_len);
374  if (line_state->db == NULL) {
375  return -1;
376  }
377  line_state->current_line_db = 1;
378  memcpy(line_state->db, state->input, state->input_len);
379  line_state->db_len = state->input_len;
380  } else {
381  ptmp = FTPRealloc(line_state->db, line_state->db_len,
382  (line_state->db_len + state->input_len));
383  if (ptmp == NULL) {
384  FTPFree(line_state->db, line_state->db_len);
385  line_state->db = NULL;
386  line_state->db_len = 0;
387  return -1;
388  }
389  line_state->db = ptmp;
390 
391  memcpy(line_state->db + line_state->db_len,
392  state->input, state->input_len);
393  line_state->db_len += state->input_len;
394  }
395  state->input += state->input_len;
396  state->input_len = 0;
397 
398  return -1;
399 
400  } else {
401  line_state->current_line_lf_seen = 1;
402 
403  if (line_state->current_line_db == 1) {
404  ptmp = FTPRealloc(line_state->db, line_state->db_len,
405  (line_state->db_len + (lf_idx + 1 - state->input)));
406  if (ptmp == NULL) {
407  FTPFree(line_state->db, line_state->db_len);
408  line_state->db = NULL;
409  line_state->db_len = 0;
410  return -1;
411  }
412  line_state->db = ptmp;
413 
414  memcpy(line_state->db + line_state->db_len,
415  state->input, (lf_idx + 1 - state->input));
416  line_state->db_len += (lf_idx + 1 - state->input);
417 
418  if (line_state->db_len > 1 &&
419  line_state->db[line_state->db_len - 2] == 0x0D) {
420  line_state->db_len -= 2;
421  state->current_line_delimiter_len = 2;
422  } else {
423  line_state->db_len -= 1;
424  state->current_line_delimiter_len = 1;
425  }
426 
427  state->current_line = line_state->db;
428  state->current_line_len = line_state->db_len;
429 
430  } else {
431  state->current_line = state->input;
432  state->current_line_len = lf_idx - state->input;
433 
434  if (state->input != lf_idx &&
435  *(lf_idx - 1) == 0x0D) {
436  state->current_line_len--;
437  state->current_line_delimiter_len = 2;
438  } else {
439  state->current_line_delimiter_len = 1;
440  }
441  }
442 
443  state->input_len -= (lf_idx - state->input) + 1;
444  state->input = (lf_idx + 1);
445 
446  return 0;
447  }
448 
449 }
450 
451 static int FTPGetLine(FtpState *state)
452 {
453  SCEnter();
454 
455  /* we have run out of input */
456  if (state->input_len <= 0)
457  return -1;
458 
459  /* toserver */
460  if (state->direction == 0)
461  return FTPGetLineForDirection(state, &state->line_state[0]);
462  else
463  return FTPGetLineForDirection(state, &state->line_state[1]);
464 }
465 
466 /**
467  * \brief This function is called to determine and set which command is being
468  * transferred to the ftp server
469  * \param thread context
470  * \param input input line of the command
471  * \param len of the command
472  * \param cmd_descriptor when the command has been parsed
473  *
474  * \retval 1 when the command is parsed, 0 otherwise
475  */
476 static int FTPParseRequestCommand(FTPThreadCtx *td,
477  const uint8_t *input, uint32_t input_len,
478  const FtpCommand **cmd_descriptor)
479 {
480  SCEnter();
481 
482  /* I don't like this pmq reset here. We'll devise a method later, that
483  * should make the use of the mpm very efficient */
484  PmqReset(td->pmq);
485  int mpm_cnt = mpm_table[FTP_MPM].Search(ftp_mpm_ctx, td->ftp_mpm_thread_ctx,
486  td->pmq, input, input_len);
487  if (mpm_cnt) {
488  *cmd_descriptor = &FtpCommands[td->pmq->rule_id_array[0]];
489  SCReturnInt(1);
490  }
491 
492  *cmd_descriptor = NULL;
493  SCReturnInt(0);
494 }
495 
497  /** Need to look like a ExpectationData so DFree must
498  * be first field . */
499  void (*DFree)(void *);
500  uint64_t flow_id;
501  uint8_t *file_name;
502  uint16_t file_len;
504 };
505 
506 static void FtpTransferCmdFree(void *data)
507 {
508  struct FtpTransferCmd *cmd = (struct FtpTransferCmd *) data;
509  if (cmd == NULL)
510  return;
511  if (cmd->file_name) {
512  FTPFree(cmd->file_name, cmd->file_len + 1);
513  }
514  FTPFree(cmd, sizeof(struct FtpTransferCmd));
515 }
516 
517 static uint32_t CopyCommandLine(uint8_t **dest, const uint8_t *src, uint32_t length)
518 {
519  if (likely(length)) {
520  uint8_t *where = FTPCalloc(length + 1, sizeof(char));
521  if (unlikely(where == NULL)) {
522  return 0;
523  }
524  memcpy(where, src, length);
525 
526  /* Remove trailing newlines/carriage returns */
527  while (length && isspace((unsigned char) where[length - 1])) {
528  length--;
529  }
530 
531  where[length] = '\0';
532  *dest = where;
533  }
534  /* either 0 or actual */
535  return length ? length + 1 : 0;
536 }
537 
538 
539 /**
540  * \brief This function is called to retrieve a ftp request
541  * \param ftp_state the ftp state structure for the parser
542  * \param input input line of the command
543  * \param input_len length of the request
544  * \param output the resulting output
545  *
546  * \retval APP_LAYER_OK when input was process successfully
547  * \retval APP_LAYER_ERROR when a unrecoverable error was encountered
548  */
549 static AppLayerResult FTPParseRequest(Flow *f, void *ftp_state,
550  AppLayerParserState *pstate,
551  const uint8_t *input, uint32_t input_len,
552  void *local_data, const uint8_t flags)
553 {
554  FTPThreadCtx *thread_data = local_data;
555 
556  SCEnter();
557  /* PrintRawDataFp(stdout, input,input_len); */
558 
559  FtpState *state = (FtpState *)ftp_state;
560  void *ptmp;
561 
562  if (input == NULL && AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF_TS)) {
564  } else if (input == NULL || input_len == 0) {
566  }
567 
568  state->input = input;
569  state->input_len = input_len;
570  /* toserver stream */
571  state->direction = 0;
572 
573  int direction = STREAM_TOSERVER;
574  while (FTPGetLine(state) >= 0) {
575  const FtpCommand *cmd_descriptor;
576 
577  if (!FTPParseRequestCommand(thread_data,
578  state->current_line, state->current_line_len,
579  &cmd_descriptor)) {
580  state->command = FTP_COMMAND_UNKNOWN;
581  continue;
582  }
583 
584  state->command = cmd_descriptor->command;
585 
586  FTPTransaction *tx = FTPTransactionCreate(state);
587  if (unlikely(tx == NULL))
589  state->curr_tx = tx;
590 
591  tx->command_descriptor = cmd_descriptor;
592  tx->request_length = CopyCommandLine(&tx->request,
593  state->current_line, state->current_line_len);
594 
595  /* change direction (default to server) so expectation will handle
596  * the correct message when expectation will match.
597  * For ftp active mode, data connection direction is opposite to
598  * control direction.
599  */
600  if ((state->active && state->command == FTP_COMMAND_STOR) ||
601  (!state->active && state->command == FTP_COMMAND_RETR)) {
602  direction = STREAM_TOCLIENT;
603  }
604 
605  switch (state->command) {
606  case FTP_COMMAND_EPRT:
607  // fallthrough
608  case FTP_COMMAND_PORT:
609  if (state->current_line_len + 1 > state->port_line_size) {
610  /* Allocate an extra byte for a NULL terminator */
611  ptmp = FTPRealloc(state->port_line, state->port_line_size,
612  state->current_line_len);
613  if (ptmp == NULL) {
614  if (state->port_line) {
615  FTPFree(state->port_line, state->port_line_size);
616  state->port_line = NULL;
617  state->port_line_size = 0;
618  }
620  }
621  state->port_line = ptmp;
622  state->port_line_size = state->current_line_len;
623  }
624  memcpy(state->port_line, state->current_line,
625  state->current_line_len);
626  state->port_line_len = state->current_line_len;
627  break;
628  case FTP_COMMAND_RETR:
629  // fallthrough
630  case FTP_COMMAND_STOR: {
631  /* Ensure that there is a negotiated dyn port and a file
632  * name -- need more than 5 chars: cmd [4], space, <filename>
633  */
634  if (state->dyn_port == 0 || state->current_line_len < 6) {
636  }
637  struct FtpTransferCmd *data = FTPCalloc(1, sizeof(struct FtpTransferCmd));
638  if (data == NULL)
640  data->DFree = FtpTransferCmdFree;
641  /*
642  * Min size has been checked in FTPParseRequestCommand
643  * PATH_MAX includes the null
644  */
645  int file_name_len = MIN(PATH_MAX - 1, state->current_line_len - 5);
646  data->file_name = FTPCalloc(file_name_len + 1, sizeof(char));
647  if (data->file_name == NULL) {
648  FtpTransferCmdFree(data);
650  }
651  data->file_name[file_name_len] = 0;
652  data->file_len = file_name_len;
653  memcpy(data->file_name, state->current_line + 5, file_name_len);
654  data->cmd = state->command;
655  data->flow_id = FlowGetId(f);
656  int ret = AppLayerExpectationCreate(f, direction,
657  0, state->dyn_port, ALPROTO_FTPDATA, data);
658  if (ret == -1) {
659  FtpTransferCmdFree(data);
660  SCLogDebug("No expectation created.");
662  } else {
663  SCLogDebug("Expectation created [direction: %s, dynamic port %"PRIu16"].",
664  state->active ? "to server" : "to client",
665  state->dyn_port);
666  }
667 
668  /* reset the dyn port to avoid duplicate */
669  state->dyn_port = 0;
670  /* reset active/passive indicator */
671  state->active = false;
672  }
673  break;
674  default:
675  break;
676  }
677  }
678 
680 }
681 
682 static int FTPParsePassiveResponse(Flow *f, FtpState *state, const uint8_t *input, uint32_t input_len)
683 {
684  uint16_t dyn_port = rs_ftp_pasv_response(input, input_len);
685  if (dyn_port == 0) {
686  return -1;
687  }
688  SCLogDebug("FTP passive mode (v4): dynamic port %"PRIu16"", dyn_port);
689  state->active = false;
690  state->dyn_port = dyn_port;
691  state->curr_tx->dyn_port = dyn_port;
692  state->curr_tx->active = false;
693 
694  return 0;
695 }
696 
697 static int FTPParsePassiveResponseV6(Flow *f, FtpState *state, const uint8_t *input, uint32_t input_len)
698 {
699  uint16_t dyn_port = rs_ftp_epsv_response(input, input_len);
700  if (dyn_port == 0) {
701  return -1;
702  }
703  SCLogDebug("FTP passive mode (v6): dynamic port %"PRIu16"", dyn_port);
704  state->active = false;
705  state->dyn_port = dyn_port;
706  state->curr_tx->dyn_port = dyn_port;
707  state->curr_tx->active = false;
708  return 0;
709 }
710 
711 /**
712  * \brief Handle preliminary replies -- keep tx open
713  * \retval bool True for a positive preliminary reply; false otherwise
714  *
715  * 1yz Positive Preliminary reply
716  *
717  * The requested action is being initiated; expect another
718  * reply before proceeding with a new command
719  */
720 static inline bool FTPIsPPR(const uint8_t *input, uint32_t input_len)
721 {
722  return input_len >= 4 && isdigit(input[0]) && input[0] == '1' &&
723  isdigit(input[1]) && isdigit(input[2]) && isspace(input[3]);
724 }
725 
726 /**
727  * \brief This function is called to retrieve a ftp response
728  * \param ftp_state the ftp state structure for the parser
729  * \param input input line of the command
730  * \param input_len length of the request
731  * \param output the resulting output
732  *
733  * \retval 1 when the command is parsed, 0 otherwise
734  */
735 static AppLayerResult FTPParseResponse(Flow *f, void *ftp_state, AppLayerParserState *pstate,
736  const uint8_t *input, uint32_t input_len,
737  void *local_data, const uint8_t flags)
738 {
739  FtpState *state = (FtpState *)ftp_state;
740 
741  if (unlikely(input_len == 0)) {
743  }
744  state->input = input;
745  state->input_len = input_len;
746  /* toclient stream */
747  state->direction = 1;
748 
749  FTPTransaction *lasttx = TAILQ_FIRST(&state->tx_list);
750  while (FTPGetLine(state) >= 0) {
751  FTPTransaction *tx = FTPGetOldestTx(state, lasttx);
752  if (tx == NULL) {
753  tx = FTPTransactionCreate(state);
754  }
755  if (unlikely(tx == NULL)) {
757  }
758  lasttx = tx;
759  if (state->command == FTP_COMMAND_UNKNOWN || tx->command_descriptor == NULL) {
760  /* unknown */
762  }
763 
764  state->curr_tx = tx;
765  uint16_t dyn_port;
766  switch (state->command) {
768  if (state->current_line_len >= 4 && SCMemcmp("234 ", state->current_line, 4) == 0) {
770  }
771  break;
772 
773  case FTP_COMMAND_EPRT:
774  dyn_port = rs_ftp_active_eprt(state->port_line, state->port_line_len);
775  if (dyn_port == 0) {
776  goto tx_complete;
777  }
778  state->dyn_port = dyn_port;
779  state->active = true;
780  tx->dyn_port = dyn_port;
781  tx->active = true;
782  SCLogDebug("FTP active mode (v6): dynamic port %"PRIu16"", dyn_port);
783  break;
784 
785  case FTP_COMMAND_PORT:
786  dyn_port = rs_ftp_active_port(state->port_line, state->port_line_len);
787  if (dyn_port == 0) {
788  goto tx_complete;
789  }
790  state->dyn_port = dyn_port;
791  state->active = true;
792  tx->dyn_port = state->dyn_port;
793  tx->active = true;
794  SCLogDebug("FTP active mode (v4): dynamic port %"PRIu16"", dyn_port);
795  break;
796 
797  case FTP_COMMAND_PASV:
798  if (state->current_line_len >= 4 && SCMemcmp("227 ", state->current_line, 4) == 0) {
799  FTPParsePassiveResponse(f, ftp_state, state->current_line, state->current_line_len);
800  }
801  break;
802 
803  case FTP_COMMAND_EPSV:
804  if (state->current_line_len >= 4 && SCMemcmp("229 ", state->current_line, 4) == 0) {
805  FTPParsePassiveResponseV6(f, ftp_state, state->current_line, state->current_line_len);
806  }
807  break;
808  default:
809  break;
810  }
811 
812  if (likely(state->current_line_len)) {
813  FTPString *response = FTPStringAlloc();
814  if (likely(response)) {
815  response->len = CopyCommandLine(&response->str, state->current_line, state->current_line_len);
816  TAILQ_INSERT_TAIL(&tx->response_list, response, next);
817  }
818  }
819 
820  /* Handle preliminary replies -- keep tx open */
821  if (FTPIsPPR(state->current_line, state->current_line_len)) {
822  continue;
823  }
824  tx_complete:
825  tx->done = true;
826  }
827 
829 }
830 
831 
832 #ifdef DEBUG
833 static SCMutex ftp_state_mem_lock = SCMUTEX_INITIALIZER;
834 static uint64_t ftp_state_memuse = 0;
835 static uint64_t ftp_state_memcnt = 0;
836 #endif
837 
838 static void *FTPStateAlloc(void *orig_state, AppProto proto_orig)
839 {
840  void *s = FTPCalloc(1, sizeof(FtpState));
841  if (unlikely(s == NULL))
842  return NULL;
843 
844  FtpState *ftp_state = (FtpState *) s;
845  TAILQ_INIT(&ftp_state->tx_list);
846 
847 #ifdef DEBUG
848  SCMutexLock(&ftp_state_mem_lock);
849  ftp_state_memcnt++;
850  ftp_state_memuse+=sizeof(FtpState);
851  SCMutexUnlock(&ftp_state_mem_lock);
852 #endif
853  return s;
854 }
855 
856 static void FTPStateFree(void *s)
857 {
858  FtpState *fstate = (FtpState *) s;
859  if (fstate->port_line != NULL)
860  FTPFree(fstate->port_line, fstate->port_line_size);
861  if (fstate->line_state[0].db)
862  FTPFree(fstate->line_state[0].db, fstate->line_state[0].db_len);
863  if (fstate->line_state[1].db)
864  FTPFree(fstate->line_state[1].db, fstate->line_state[1].db_len);
865 
866  //AppLayerDecoderEventsFreeEvents(&s->decoder_events);
867 
868  FTPTransaction *tx = NULL;
869  while ((tx = TAILQ_FIRST(&fstate->tx_list))) {
870  TAILQ_REMOVE(&fstate->tx_list, tx, next);
871  SCLogDebug("[%s] state %p id %"PRIu64", Freeing %d bytes at %p",
873  s, tx->tx_id,
874  tx->request_length, tx->request);
875  FTPTransactionFree(tx);
876  }
877 
878  FTPFree(s, sizeof(FtpState));
879 #ifdef DEBUG
880  SCMutexLock(&ftp_state_mem_lock);
881  ftp_state_memcnt--;
882  ftp_state_memuse-=sizeof(FtpState);
883  SCMutexUnlock(&ftp_state_mem_lock);
884 #endif
885 }
886 
887 static int FTPSetTxDetectState(void *vtx, DetectEngineState *de_state)
888 {
889  FTPTransaction *tx = (FTPTransaction *)vtx;
890  tx->de_state = de_state;
891  return 0;
892 }
893 
894 /**
895  * \brief This function returns the oldest open transaction; if none
896  * are open, then the oldest transaction is returned
897  * \param ftp_state the ftp state structure for the parser
898  * \param starttx the ftp transaction where to start looking
899  *
900  * \retval transaction pointer when a transaction was found; NULL otherwise.
901  */
902 static FTPTransaction *FTPGetOldestTx(FtpState *ftp_state, FTPTransaction *starttx)
903 {
904  if (unlikely(!ftp_state)) {
905  SCLogDebug("NULL state object; no transactions available");
906  return NULL;
907  }
908  FTPTransaction *tx = starttx;
909  FTPTransaction *lasttx = NULL;
910  while(tx != NULL) {
911  /* Return oldest open tx */
912  if (!tx->done) {
913  SCLogDebug("Returning tx %p id %"PRIu64, tx, tx->tx_id);
914  return tx;
915  }
916  /* save for the end */
917  lasttx = tx;
918  tx = TAILQ_NEXT(tx, next);
919  }
920  /* All tx are closed; return last element */
921  if (lasttx)
922  SCLogDebug("Returning OLDEST tx %p id %"PRIu64, lasttx, lasttx->tx_id);
923  return lasttx;
924 }
925 
926 static void *FTPGetTx(void *state, uint64_t tx_id)
927 {
928  FtpState *ftp_state = (FtpState *)state;
929  if (ftp_state) {
930  FTPTransaction *tx = NULL;
931 
932  if (ftp_state->curr_tx == NULL)
933  return NULL;
934  if (ftp_state->curr_tx->tx_id == tx_id)
935  return ftp_state->curr_tx;
936 
937  TAILQ_FOREACH(tx, &ftp_state->tx_list, next) {
938  if (tx->tx_id == tx_id)
939  return tx;
940  }
941  }
942  return NULL;
943 }
944 
945 static DetectEngineState *FTPGetTxDetectState(void *vtx)
946 {
947  FTPTransaction *tx = (FTPTransaction *)vtx;
948  return tx->de_state;
949 }
950 
951 
952 static AppLayerTxData *FTPGetTxData(void *vtx)
953 {
954  FTPTransaction *tx = (FTPTransaction *)vtx;
955  return &tx->tx_data;
956 }
957 
958 static void FTPStateTransactionFree(void *state, uint64_t tx_id)
959 {
960  FtpState *ftp_state = state;
961  FTPTransaction *tx = NULL;
962  TAILQ_FOREACH(tx, &ftp_state->tx_list, next) {
963  if (tx_id < tx->tx_id)
964  break;
965  else if (tx_id > tx->tx_id)
966  continue;
967 
968  if (tx == ftp_state->curr_tx)
969  ftp_state->curr_tx = NULL;
970  TAILQ_REMOVE(&ftp_state->tx_list, tx, next);
971  FTPTransactionFree(tx);
972  break;
973  }
974 }
975 
976 static uint64_t FTPGetTxCnt(void *state)
977 {
978  uint64_t cnt = 0;
979  FtpState *ftp_state = state;
980  if (ftp_state) {
981  cnt = ftp_state->tx_cnt;
982  }
983  SCLogDebug("returning state %p %"PRIu64, state, cnt);
984  return cnt;
985 }
986 
987 static int FTPGetAlstateProgress(void *vtx, uint8_t direction)
988 {
989  SCLogDebug("tx %p", vtx);
990  FTPTransaction *tx = vtx;
991 
992  if (!tx->done) {
993  if (direction == STREAM_TOSERVER &&
995  return FTP_STATE_PORT_DONE;
996  }
997  return FTP_STATE_IN_PROGRESS;
998  }
999 
1000  return FTP_STATE_FINISHED;
1001 }
1002 
1003 
1004 static int FTPRegisterPatternsForProtocolDetection(void)
1005 {
1007  "220 (", 5, 0, STREAM_TOCLIENT) < 0)
1008  {
1009  return -1;
1010  }
1012  "FEAT", 4, 0, STREAM_TOSERVER) < 0)
1013  {
1014  return -1;
1015  }
1017  "USER ", 5, 0, STREAM_TOSERVER) < 0)
1018  {
1019  return -1;
1020  }
1022  "PASS ", 5, 0, STREAM_TOSERVER) < 0)
1023  {
1024  return -1;
1025  }
1027  "PORT ", 5, 0, STREAM_TOSERVER) < 0)
1028  {
1029  return -1;
1030  }
1031 
1032  return 0;
1033 }
1034 
1035 
1037 
1038 /**
1039  * \brief This function is called to retrieve a ftp request
1040  * \param ftp_state the ftp state structure for the parser
1041  * \param input input line of the command
1042  * \param input_len length of the request
1043  * \param output the resulting output
1044  *
1045  * \retval 1 when the command is parsed, 0 otherwise
1046  */
1047 static AppLayerResult FTPDataParse(Flow *f, FtpDataState *ftpdata_state,
1048  AppLayerParserState *pstate,
1049  const uint8_t *input, uint32_t input_len,
1050  void *local_data, int direction)
1051 {
1052  uint16_t flags = FileFlowToFlags(f, direction);
1053  int ret = 0;
1054  /* we depend on detection engine for file pruning */
1056  if (ftpdata_state->files == NULL) {
1057  struct FtpTransferCmd *data =
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  ftpdata_state->tx_data.files_opened = 1;
1097  } else {
1098  if (input_len != 0) {
1099  ret = FileAppendData(ftpdata_state->files, input, input_len);
1100  if (ret == -2) {
1101  ret = 0;
1102  SCLogDebug("FileAppendData() - file no longer being extracted");
1103  goto out;
1104  } else if (ret < 0) {
1105  SCLogDebug("FileAppendData() failed: %d", ret);
1106  ret = -2;
1107  goto out;
1108  }
1109  } else {
1110  ret = FileCloseFile(ftpdata_state->files, NULL, 0, flags);
1111  ftpdata_state->state = FTPDATA_STATE_FINISHED;
1112  if (ret < 0)
1113  goto out;
1114  }
1115  }
1116 
1117  const bool eof_flag = flags & STREAM_TOSERVER ?
1120  if (input_len && eof_flag) {
1121  ret = FileCloseFile(ftpdata_state->files, (uint8_t *) NULL, 0, flags);
1122  ftpdata_state->state = FTPDATA_STATE_FINISHED;
1123  }
1124 
1125 out:
1126  if (ret < 0) {
1128  }
1130 }
1131 
1132 static AppLayerResult FTPDataParseRequest(Flow *f, void *ftp_state,
1133  AppLayerParserState *pstate,
1134  const uint8_t *input, uint32_t input_len,
1135  void *local_data, const uint8_t flags)
1136 {
1137  return FTPDataParse(f, ftp_state, pstate, input, input_len,
1138  local_data, STREAM_TOSERVER);
1139 }
1140 
1141 static AppLayerResult FTPDataParseResponse(Flow *f, void *ftp_state,
1142  AppLayerParserState *pstate,
1143  const uint8_t *input, uint32_t input_len,
1144  void *local_data, const uint8_t flags)
1145 {
1146  return FTPDataParse(f, ftp_state, pstate, input, input_len,
1147  local_data, STREAM_TOCLIENT);
1148 }
1149 
1150 #ifdef DEBUG
1151 static SCMutex ftpdata_state_mem_lock = SCMUTEX_INITIALIZER;
1152 static uint64_t ftpdata_state_memuse = 0;
1153 static uint64_t ftpdata_state_memcnt = 0;
1154 #endif
1155 
1156 static void *FTPDataStateAlloc(void *orig_state, AppProto proto_orig)
1157 {
1158  void *s = FTPCalloc(1, sizeof(FtpDataState));
1159  if (unlikely(s == NULL))
1160  return NULL;
1161 
1162  FtpDataState *state = (FtpDataState *) s;
1164 
1165 #ifdef DEBUG
1166  SCMutexLock(&ftpdata_state_mem_lock);
1167  ftpdata_state_memcnt++;
1168  ftpdata_state_memuse+=sizeof(FtpDataState);
1169  SCMutexUnlock(&ftpdata_state_mem_lock);
1170 #endif
1171  return s;
1172 }
1173 
1174 static void FTPDataStateFree(void *s)
1175 {
1176  FtpDataState *fstate = (FtpDataState *) s;
1177 
1178  if (fstate->de_state != NULL) {
1180  }
1181  if (fstate->file_name != NULL) {
1182  FTPFree(fstate->file_name, fstate->file_len + 1);
1183  }
1184 
1185  FileContainerFree(fstate->files);
1186 
1187  FTPFree(s, sizeof(FtpDataState));
1188 #ifdef DEBUG
1189  SCMutexLock(&ftpdata_state_mem_lock);
1190  ftpdata_state_memcnt--;
1191  ftpdata_state_memuse-=sizeof(FtpDataState);
1192  SCMutexUnlock(&ftpdata_state_mem_lock);
1193 #endif
1194 }
1195 
1196 static int FTPDataSetTxDetectState(void *vtx, DetectEngineState *de_state)
1197 {
1198  FtpDataState *ftp_state = (FtpDataState *)vtx;
1199  ftp_state->de_state = de_state;
1200  return 0;
1201 }
1202 
1203 static DetectEngineState *FTPDataGetTxDetectState(void *vtx)
1204 {
1205  FtpDataState *ftp_state = (FtpDataState *)vtx;
1206  return ftp_state->de_state;
1207 }
1208 
1209 static AppLayerTxData *FTPDataGetTxData(void *vtx)
1210 {
1211  FtpDataState *ftp_state = (FtpDataState *)vtx;
1212  return &ftp_state->tx_data;
1213 }
1214 
1215 static void FTPDataStateTransactionFree(void *state, uint64_t tx_id)
1216 {
1217  /* do nothing */
1218 }
1219 
1220 static void *FTPDataGetTx(void *state, uint64_t tx_id)
1221 {
1222  FtpDataState *ftp_state = (FtpDataState *)state;
1223  return ftp_state;
1224 }
1225 
1226 static uint64_t FTPDataGetTxCnt(void *state)
1227 {
1228  /* ftp-data is single tx */
1229  return 1;
1230 }
1231 
1232 static int FTPDataGetAlstateProgress(void *tx, uint8_t direction)
1233 {
1234  FtpDataState *ftpdata_state = (FtpDataState *)tx;
1235  return ftpdata_state->state;
1236 }
1237 
1238 static FileContainer *FTPDataStateGetFiles(void *state, uint8_t direction)
1239 {
1240  FtpDataState *ftpdata_state = (FtpDataState *)state;
1241 
1242  if (direction != ftpdata_state->direction)
1243  SCReturnPtr(NULL, "FileContainer");
1244 
1245  SCReturnPtr(ftpdata_state->files, "FileContainer");
1246 }
1247 
1248 static void FTPSetMpmState(void)
1249 {
1250  ftp_mpm_ctx = SCMalloc(sizeof(MpmCtx));
1251  if (unlikely(ftp_mpm_ctx == NULL)) {
1252  exit(EXIT_FAILURE);
1253  }
1254  memset(ftp_mpm_ctx, 0, sizeof(MpmCtx));
1255  MpmInitCtx(ftp_mpm_ctx, FTP_MPM);
1256 
1257  uint32_t i = 0;
1258  for (i = 0; i < sizeof(FtpCommands)/sizeof(FtpCommand) - 1; i++) {
1259  const FtpCommand *cmd = &FtpCommands[i];
1260  if (cmd->command_length == 0)
1261  continue;
1262 
1263  MpmAddPatternCI(ftp_mpm_ctx,
1264  (uint8_t *)cmd->command_name,
1265  cmd->command_length,
1266  0 /* defunct */, 0 /* defunct */,
1267  i /* id */, i /* rule id */ , 0 /* no flags */);
1268  }
1269 
1270  mpm_table[FTP_MPM].Prepare(ftp_mpm_ctx);
1271 
1272 }
1273 
1274 static void FTPFreeMpmState(void)
1275 {
1276  if (ftp_mpm_ctx != NULL) {
1277  mpm_table[FTP_MPM].DestroyCtx(ftp_mpm_ctx);
1278  SCFree(ftp_mpm_ctx);
1279  ftp_mpm_ctx = NULL;
1280  }
1281 }
1282 
1284 {
1285  const char *proto_name = "ftp";
1286  const char *proto_data_name = "ftp-data";
1287 
1288  /** FTP */
1289  if (AppLayerProtoDetectConfProtoDetectionEnabled("tcp", proto_name)) {
1291  if (FTPRegisterPatternsForProtocolDetection() < 0 )
1292  return;
1294  }
1295 
1296  if (AppLayerParserConfParserEnabled("tcp", proto_name)) {
1298  FTPParseRequest);
1300  FTPParseResponse);
1301  AppLayerParserRegisterStateFuncs(IPPROTO_TCP, ALPROTO_FTP, FTPStateAlloc, FTPStateFree);
1303 
1304  AppLayerParserRegisterTxFreeFunc(IPPROTO_TCP, ALPROTO_FTP, FTPStateTransactionFree);
1305 
1307  FTPGetTxDetectState, FTPSetTxDetectState);
1308 
1309  AppLayerParserRegisterGetTx(IPPROTO_TCP, ALPROTO_FTP, FTPGetTx);
1310  AppLayerParserRegisterTxDataFunc(IPPROTO_TCP, ALPROTO_FTP, FTPGetTxData);
1311 
1312  AppLayerParserRegisterLocalStorageFunc(IPPROTO_TCP, ALPROTO_FTP, FTPLocalStorageAlloc,
1313  FTPLocalStorageFree);
1314  AppLayerParserRegisterGetTxCnt(IPPROTO_TCP, ALPROTO_FTP, FTPGetTxCnt);
1315 
1316  AppLayerParserRegisterGetStateProgressFunc(IPPROTO_TCP, ALPROTO_FTP, FTPGetAlstateProgress);
1317 
1320 
1323  FTPDataParseRequest);
1325  FTPDataParseResponse);
1326  AppLayerParserRegisterStateFuncs(IPPROTO_TCP, ALPROTO_FTPDATA, FTPDataStateAlloc, FTPDataStateFree);
1328  AppLayerParserRegisterTxFreeFunc(IPPROTO_TCP, ALPROTO_FTPDATA, FTPDataStateTransactionFree);
1330  FTPDataGetTxDetectState, FTPDataSetTxDetectState);
1331 
1332  AppLayerParserRegisterGetFilesFunc(IPPROTO_TCP, ALPROTO_FTPDATA, FTPDataStateGetFiles);
1333 
1334  AppLayerParserRegisterGetTx(IPPROTO_TCP, ALPROTO_FTPDATA, FTPDataGetTx);
1335  AppLayerParserRegisterTxDataFunc(IPPROTO_TCP, ALPROTO_FTPDATA, FTPDataGetTxData);
1336 
1337  AppLayerParserRegisterGetTxCnt(IPPROTO_TCP, ALPROTO_FTPDATA, FTPDataGetTxCnt);
1338 
1339  AppLayerParserRegisterGetStateProgressFunc(IPPROTO_TCP, ALPROTO_FTPDATA, FTPDataGetAlstateProgress);
1340 
1343 
1344  sbcfg.buf_size = 4096;
1345  sbcfg.Malloc = FTPMalloc;
1346  sbcfg.Calloc = FTPCalloc;
1347  sbcfg.Realloc = FTPRealloc;
1348  sbcfg.Free = FTPFree;
1349 
1350  FTPParseMemcap();
1351  } else {
1352  SCLogInfo("Parsed disabled for %s protocol. Protocol detection"
1353  "still on.", proto_name);
1354  }
1355 
1356  FTPSetMpmState();
1357 
1358 #ifdef UNITTESTS
1360 #endif
1361 }
1362 
1364 {
1365 #ifdef DEBUG
1366  SCMutexLock(&ftp_state_mem_lock);
1367  SCLogDebug("ftp_state_memcnt %"PRIu64", ftp_state_memuse %"PRIu64"",
1368  ftp_state_memcnt, ftp_state_memuse);
1369  SCMutexUnlock(&ftp_state_mem_lock);
1370 #endif
1371 }
1372 
1373 
1374 /*
1375  * \brief Returns the ending offset of the next line from a multi-line buffer.
1376  *
1377  * "Buffer" refers to a FTP response in a single buffer containing multiple lines.
1378  * Here, "next line" is defined as terminating on
1379  * - Newline character
1380  * - Null character
1381  *
1382  * \param buffer Contains zero or more characters.
1383  * \param len Size, in bytes, of buffer.
1384  *
1385  * \retval Offset from the start of buffer indicating the where the
1386  * next "line ends". The characters between the input buffer and this
1387  * value comprise the line.
1388  *
1389  * NULL is found first or a newline isn't found, then UINT16_MAX is returned.
1390  */
1391 uint16_t JsonGetNextLineFromBuffer(const char *buffer, const uint16_t len)
1392 {
1393  if (!buffer || *buffer == '\0') {
1394  return UINT16_MAX;
1395  }
1396 
1397  char *c = strchr(buffer, '\n');
1398  return c == NULL ? len : c - buffer + 1;
1399 }
1400 
1401 void EveFTPDataAddMetadata(const Flow *f, JsonBuilder *jb)
1402 {
1403  const FtpDataState *ftp_state = NULL;
1404  if (f->alstate == NULL)
1405  return;
1406 
1407  ftp_state = (FtpDataState *)f->alstate;
1408 
1409  if (ftp_state->file_name) {
1410  jb_set_string_from_bytes(jb, "filename", ftp_state->file_name, ftp_state->file_len);
1411  }
1412  switch (ftp_state->command) {
1413  case FTP_COMMAND_STOR:
1414  JB_SET_STRING(jb, "command", "STOR");
1415  break;
1416  case FTP_COMMAND_RETR:
1417  JB_SET_STRING(jb, "command", "RETR");
1418  break;
1419  default:
1420  break;
1421  }
1422 }
1423 
1424 /**
1425  * \brief Free memory allocated for global FTP parser state.
1426  */
1428 {
1429  FTPFreeMpmState();
1430 }
1431 
1432 /* UNITTESTS */
1433 #ifdef UNITTESTS
1434 
1435 /** \test Send a get request in one chunk. */
1436 static int FTPParserTest01(void)
1437 {
1438  Flow f;
1439  uint8_t ftpbuf[] = "PORT 192,168,1,1,0,80\r\n";
1440  uint32_t ftplen = sizeof(ftpbuf) - 1; /* minus the \0 */
1441  TcpSession ssn;
1443 
1444  memset(&f, 0, sizeof(f));
1445  memset(&ssn, 0, sizeof(ssn));
1446 
1447  f.protoctx = (void *)&ssn;
1448  f.proto = IPPROTO_TCP;
1449  f.alproto = ALPROTO_FTP;
1450 
1451  StreamTcpInitConfig(true);
1452 
1453  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_FTP,
1454  STREAM_TOSERVER | STREAM_EOF, ftpbuf, ftplen);
1455  FAIL_IF(r != 0);
1456 
1457  FtpState *ftp_state = f.alstate;
1458  FAIL_IF_NULL(ftp_state);
1459  FAIL_IF(ftp_state->command != FTP_COMMAND_PORT);
1460 
1462  StreamTcpFreeConfig(true);
1463  PASS;
1464 }
1465 
1466 /** \test Send a split get request. */
1467 static int FTPParserTest03(void)
1468 {
1469  Flow f;
1470  uint8_t ftpbuf1[] = "POR";
1471  uint32_t ftplen1 = sizeof(ftpbuf1) - 1; /* minus the \0 */
1472  uint8_t ftpbuf2[] = "T 192,168,1";
1473  uint32_t ftplen2 = sizeof(ftpbuf2) - 1; /* minus the \0 */
1474  uint8_t ftpbuf3[] = "1,1,10,20\r\n";
1475  uint32_t ftplen3 = sizeof(ftpbuf3) - 1; /* minus the \0 */
1476  TcpSession ssn;
1478 
1479  memset(&f, 0, sizeof(f));
1480  memset(&ssn, 0, sizeof(ssn));
1481 
1482  f.protoctx = (void *)&ssn;
1483  f.proto = IPPROTO_TCP;
1484  f.alproto = ALPROTO_FTP;
1485 
1486  StreamTcpInitConfig(true);
1487 
1488  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_FTP,
1489  STREAM_TOSERVER | STREAM_START, ftpbuf1,
1490  ftplen1);
1491  FAIL_IF(r != 0);
1492 
1494  ftpbuf2, ftplen2);
1495  FAIL_IF(r != 0);
1496 
1497  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_FTP,
1498  STREAM_TOSERVER | STREAM_EOF, ftpbuf3, ftplen3);
1499  FAIL_IF(r != 0);
1500 
1501  FtpState *ftp_state = f.alstate;
1502  FAIL_IF_NULL(ftp_state);
1503 
1504  FAIL_IF(ftp_state->command != FTP_COMMAND_PORT);
1505 
1507  StreamTcpFreeConfig(true);
1508  PASS;
1509 }
1510 
1511 /** \test See how it deals with an incomplete request. */
1512 static int FTPParserTest06(void)
1513 {
1514  Flow f;
1515  uint8_t ftpbuf1[] = "PORT";
1516  uint32_t ftplen1 = sizeof(ftpbuf1) - 1; /* minus the \0 */
1517  TcpSession ssn;
1519 
1520  memset(&f, 0, sizeof(f));
1521  memset(&ssn, 0, sizeof(ssn));
1522 
1523  f.protoctx = (void *)&ssn;
1524  f.proto = IPPROTO_TCP;
1525  f.alproto = ALPROTO_FTP;
1526 
1527  StreamTcpInitConfig(true);
1528 
1529  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_FTP,
1531  ftpbuf1,
1532  ftplen1);
1533  FAIL_IF(r != 0);
1534 
1535  FtpState *ftp_state = f.alstate;
1536  FAIL_IF_NULL(ftp_state);
1537 
1538  FAIL_IF(ftp_state->command != FTP_COMMAND_UNKNOWN);
1539 
1541  StreamTcpFreeConfig(true);
1542  PASS;
1543 }
1544 
1545 /** \test See how it deals with an incomplete request in multiple chunks. */
1546 static int FTPParserTest07(void)
1547 {
1548  Flow f;
1549  uint8_t ftpbuf1[] = "PO";
1550  uint32_t ftplen1 = sizeof(ftpbuf1) - 1; /* minus the \0 */
1551  uint8_t ftpbuf2[] = "RT\r\n";
1552  uint32_t ftplen2 = sizeof(ftpbuf2) - 1; /* minus the \0 */
1553  TcpSession ssn;
1555 
1556  memset(&f, 0, sizeof(f));
1557  memset(&ssn, 0, sizeof(ssn));
1558 
1559  f.protoctx = (void *)&ssn;
1560  f.proto = IPPROTO_TCP;
1561  f.alproto = ALPROTO_FTP;
1562 
1563  StreamTcpInitConfig(true);
1564 
1565  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_FTP,
1566  STREAM_TOSERVER | STREAM_START, ftpbuf1,
1567  ftplen1);
1568  FAIL_IF(r != 0);
1569 
1570  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_FTP,
1571  STREAM_TOSERVER | STREAM_EOF, ftpbuf2, ftplen2);
1572  FAIL_IF(r != 0);
1573 
1574  FtpState *ftp_state = f.alstate;
1575  FAIL_IF_NULL(ftp_state);
1576 
1577  FAIL_IF(ftp_state->command != FTP_COMMAND_PORT);
1578 
1580  StreamTcpFreeConfig(true);
1581  PASS;
1582 }
1583 
1584 /** \test Test case where chunks are smaller than the delim length and the
1585  * last chunk is supposed to match the delim. */
1586 static int FTPParserTest10(void)
1587 {
1588  Flow f;
1589  uint8_t ftpbuf1[] = "PORT 1,2,3,4,5,6\r\n";
1590  uint32_t ftplen1 = sizeof(ftpbuf1) - 1; /* minus the \0 */
1591  TcpSession ssn;
1593  int r = 0;
1594  memset(&f, 0, sizeof(f));
1595  memset(&ssn, 0, sizeof(ssn));
1596 
1597  f.protoctx = (void *)&ssn;
1598  f.proto = IPPROTO_TCP;
1599  f.alproto = ALPROTO_FTP;
1600 
1601  StreamTcpInitConfig(true);
1602 
1603  uint32_t u;
1604  for (u = 0; u < ftplen1; u++) {
1605  uint8_t flags = 0;
1606 
1607  if (u == 0) flags = STREAM_TOSERVER|STREAM_START;
1608  else if (u == (ftplen1 - 1)) flags = STREAM_TOSERVER|STREAM_EOF;
1609  else flags = STREAM_TOSERVER;
1610 
1612  &ftpbuf1[u], 1);
1613  FAIL_IF(r != 0);
1614  }
1615 
1616  FtpState *ftp_state = f.alstate;
1617  FAIL_IF_NULL(ftp_state);
1618 
1619  FAIL_IF(ftp_state->command != FTP_COMMAND_PORT);
1620 
1622  StreamTcpFreeConfig(true);
1623  PASS;
1624 }
1625 
1626 /** \test Supply RETR without a filename */
1627 static int FTPParserTest11(void)
1628 {
1629  Flow f;
1630  uint8_t ftpbuf1[] = "PORT 192,168,1,1,0,80\r\n";
1631  uint8_t ftpbuf2[] = "RETR\r\n";
1632  uint8_t ftpbuf3[] = "227 OK\r\n";
1633  TcpSession ssn;
1634 
1636 
1637  memset(&f, 0, sizeof(f));
1638  memset(&ssn, 0, sizeof(ssn));
1639 
1640  f.protoctx = (void *)&ssn;
1641  f.proto = IPPROTO_TCP;
1642  f.alproto = ALPROTO_FTP;
1643 
1644  StreamTcpInitConfig(true);
1645 
1646  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_FTP,
1647  STREAM_TOSERVER | STREAM_START, ftpbuf1,
1648  sizeof(ftpbuf1) - 1);
1649  FAIL_IF(r != 0);
1650 
1651  /* Response */
1652  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_FTP,
1654  ftpbuf3,
1655  sizeof(ftpbuf3) - 1);
1656  FAIL_IF(r != 0);
1657 
1658  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_FTP,
1659  STREAM_TOSERVER, ftpbuf2,
1660  sizeof(ftpbuf2) - 1);
1661  FAIL_IF(r == 0);
1662 
1663  FtpState *ftp_state = f.alstate;
1664  FAIL_IF_NULL(ftp_state);
1665 
1666  FAIL_IF(ftp_state->command != FTP_COMMAND_RETR);
1667 
1669  StreamTcpFreeConfig(true);
1670  PASS;
1671 }
1672 
1673 /** \test Supply STOR without a filename */
1674 static int FTPParserTest12(void)
1675 {
1676  Flow f;
1677  uint8_t ftpbuf1[] = "PORT 192,168,1,1,0,80\r\n";
1678  uint8_t ftpbuf2[] = "STOR\r\n";
1679  uint8_t ftpbuf3[] = "227 OK\r\n";
1680  TcpSession ssn;
1681 
1683 
1684  memset(&f, 0, sizeof(f));
1685  memset(&ssn, 0, sizeof(ssn));
1686 
1687  f.protoctx = (void *)&ssn;
1688  f.proto = IPPROTO_TCP;
1689  f.alproto = ALPROTO_FTP;
1690 
1691  StreamTcpInitConfig(true);
1692 
1693  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_FTP,
1694  STREAM_TOSERVER | STREAM_START, ftpbuf1,
1695  sizeof(ftpbuf1) - 1);
1696  FAIL_IF(r != 0);
1697 
1698  /* Response */
1699  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_FTP,
1701  ftpbuf3,
1702  sizeof(ftpbuf3) - 1);
1703  FAIL_IF(r != 0);
1704 
1705  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_FTP,
1706  STREAM_TOSERVER, ftpbuf2,
1707  sizeof(ftpbuf2) - 1);
1708  FAIL_IF(r == 0);
1709 
1710  FtpState *ftp_state = f.alstate;
1711  FAIL_IF_NULL(ftp_state);
1712 
1713  FAIL_IF(ftp_state->command != FTP_COMMAND_STOR);
1714 
1716  StreamTcpFreeConfig(true);
1717  PASS;
1718 }
1719 #endif /* UNITTESTS */
1720 
1722 {
1723 #ifdef UNITTESTS
1724  UtRegisterTest("FTPParserTest01", FTPParserTest01);
1725  UtRegisterTest("FTPParserTest03", FTPParserTest03);
1726  UtRegisterTest("FTPParserTest06", FTPParserTest06);
1727  UtRegisterTest("FTPParserTest07", FTPParserTest07);
1728  UtRegisterTest("FTPParserTest10", FTPParserTest10);
1729  UtRegisterTest("FTPParserTest11", FTPParserTest11);
1730  UtRegisterTest("FTPParserTest12", FTPParserTest12);
1731 #endif /* UNITTESTS */
1732 }
1733 
MpmInitThreadCtx
void MpmInitThreadCtx(MpmThreadCtx *mpm_thread_ctx, uint16_t matcher)
Definition: util-mpm.c:195
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:474
FTPTransaction_::command_descriptor
const FtpCommand * command_descriptor
Definition: app-layer-ftp.h:145
FileContainer_
Definition: util-file.h:107
len
uint8_t len
Definition: app-layer-dnp3.h:2
FTP_COMMAND_USER
@ FTP_COMMAND_USER
Definition: app-layer-ftp.h:84
FAIL_IF_NULL
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
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:142
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:1812
FTPThreadCtx_
Definition: app-layer-ftp.c:64
FtpTransferCmd::flow_id
uint64_t flow_id
Definition: app-layer-ftp.c:500
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:410
FTP_COMMAND_ALLO
@ FTP_COMMAND_ALLO
Definition: app-layer-ftp.h:40
TAILQ_INIT
#define TAILQ_INIT(head)
Definition: queue.h:370
FtpState_::active
bool active
Definition: app-layer-ftp.h:166
flow-util.h
SC_ATOMIC_INIT
#define SC_ATOMIC_INIT(name)
wrapper for initializing an atomic variable.
Definition: util-atomic.h:315
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:426
FtpDataState_::state
uint8_t state
Definition: app-layer-ftp.h:208
StreamingBufferConfig_::Calloc
void *(* Calloc)(size_t n, size_t size)
Definition: util-streaming-buffer.h:72
DetectEngineState_
Definition: detect-engine-state.h:93
MpmThreadCtx_
Definition: util-mpm.h:46
FtpState_::input_len
int32_t input_len
Definition: app-layer-ftp.h:164
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
AppLayerExpectationGetFlowId
FlowStorageId AppLayerExpectationGetFlowId(void)
Definition: app-layer-expectation.c:289
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:202
next
struct HtpBodyChunk_ * next
Definition: app-layer-htp.h:0
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:200
FTP_COMMAND_RNFR
@ FTP_COMMAND_RNFR
Definition: app-layer-ftp.h:72
Flow_::proto
uint8_t proto
Definition: flow.h:375
AppProto
uint16_t AppProto
Definition: app-layer-protos.h:77
FtpState_::command
FtpRequestCommand command
Definition: app-layer-ftp.h:182
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:300
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:353
FTPTransaction_::done
bool done
Definition: app-layer-ftp.h:148
FTP_COMMAND_MSND
@ FTP_COMMAND_MSND
Definition: app-layer-ftp.h:59
FTP_COMMAND_EPSV
@ FTP_COMMAND_EPSV
Definition: app-layer-ftp.h:47
SC_ATOMIC_ADD
#define SC_ATOMIC_ADD(name, val)
add a value to our atomic variable
Definition: util-atomic.h:333
AppLayerParserRegisterStateProgressCompletionStatus
void AppLayerParserRegisterStateProgressCompletionStatus(AppProto alproto, const int ts, const int tc)
Definition: app-layer-parser.c:526
AppLayerParserRegisterParserAcceptableDataDirection
void AppLayerParserRegisterParserAcceptableDataDirection(uint8_t ipproto, AppProto alproto, uint8_t direction)
Definition: app-layer-parser.c:370
FTP_COMMAND_RNTO
@ FTP_COMMAND_RNTO
Definition: app-layer-ftp.h:73
FtpState_::line_state
FtpLineState line_state[2]
Definition: app-layer-ftp.h:180
AppLayerParserRegisterTxFreeFunc
void AppLayerParserRegisterTxFreeFunc(uint8_t ipproto, AppProto alproto, void(*StateTransactionFree)(void *, uint64_t))
Definition: app-layer-parser.c:485
FTP_COMMAND_MODE
@ FTP_COMMAND_MODE
Definition: app-layer-ftp.h:55
FTPTransaction_::tx_data
AppLayerTxData tx_data
Definition: app-layer-ftp.h:138
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:207
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:277
FTP_COMMAND_ABOR
@ FTP_COMMAND_ABOR
Definition: app-layer-ftp.h:38
SCMutexLock
#define SCMutexLock(mut)
Definition: threads-debug.h:117
rust.h
MIN
#define MIN(x, y)
Definition: suricata-common.h:372
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:565
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:206
TAILQ_INSERT_TAIL
#define TAILQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:385
app-layer-ftp.h
APP_LAYER_PARSER_EOF_TS
#define APP_LAYER_PARSER_EOF_TS
Definition: app-layer-parser.h:41
Flow_::protoctx
void * protoctx
Definition: flow.h:451
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:720
FtpDataState_::direction
uint8_t direction
Definition: app-layer-ftp.h:209
util-unittest.h
FtpTransferCmd::file_len
uint16_t file_len
Definition: app-layer-ftp.c:502
FtpState_::direction
uint8_t direction
Definition: app-layer-ftp.h:165
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:1427
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:195
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:196
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:330
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:162
app-layer-expectation.h
StreamTcpInitConfig
void StreamTcpInitConfig(bool)
To initialize the stream global configuration data.
Definition: stream-tcp.c:365
AppLayerParserStateIssetFlag
int AppLayerParserStateIssetFlag(AppLayerParserState *pstate, uint8_t flag)
Definition: app-layer-parser.c:1654
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:33
TAILQ_FIRST
#define TAILQ_FIRST(head)
Definition: queue.h:339
FtpState_::port_line
uint8_t * port_line
Definition: app-layer-ftp.h:186
AppLayerParserState_
Definition: app-layer-parser.c:153
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
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:234
output-json.h
FtpState_::curr_tx
FTPTransaction * curr_tx
Definition: app-layer-ftp.h:168
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:20
AppLayerParserRegisterGetFilesFunc
void AppLayerParserRegisterGetFilesFunc(uint8_t ipproto, AppProto alproto, FileContainer *(*StateGetFiles)(void *, uint8_t))
Definition: app-layer-parser.c:424
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:503
AppLayerParserRegisterStateFuncs
void AppLayerParserRegisterStateFuncs(uint8_t ipproto, AppProto alproto, void *(*StateAlloc)(void *, AppProto), void(*StateFree)(void *))
Definition: app-layer-parser.c:397
app-layer-parser.h
FtpState_::input
const uint8_t * input
Definition: app-layer-ftp.h:163
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:342
FTPParserRegisterTests
void FTPParserRegisterTests(void)
Definition: app-layer-ftp.c:1721
RegisterFTPParsers
void RegisterFTPParsers(void)
Definition: app-layer-ftp.c:1283
stream.h
AppLayerParserRegisterProtocolUnittests
void AppLayerParserRegisterProtocolUnittests(uint8_t ipproto, AppProto alproto, void(*RegisterUnittests)(void))
Definition: app-layer-parser.c:1752
AppLayerExpectationCreate
int AppLayerExpectationCreate(Flow *f, int direction, Port src, Port dst, AppProto alproto, void *data)
Definition: app-layer-expectation.c:220
FtpCommand_
Definition: app-layer-ftp.h:92
FtpTransferCmd
Definition: app-layer-ftp.c:496
stream-tcp-private.h
APP_LAYER_PARSER_EOF_TC
#define APP_LAYER_PARSER_EOF_TC
Definition: app-layer-parser.h:42
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:2204
MpmTableElmt_::Prepare
int(* Prepare)(struct MpmCtx_ *)
Definition: util-mpm.h:164
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:920
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:1889
FtpDataState
struct FtpDataState_ FtpDataState
FTP_COMMAND_ACCT
@ FTP_COMMAND_ACCT
Definition: app-layer-ftp.h:39
FlowGetStorageById
void * FlowGetStorageById(Flow *f, FlowStorageId id)
Definition: flow-storage.c: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:165
FTP_COMMAND_MRSQ
@ FTP_COMMAND_MRSQ
Definition: app-layer-ftp.h:57
FtpDataState_::tx_data
AppLayerTxData tx_data
Definition: app-layer-ftp.h:210
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:358
DetectEngineStateFree
void DetectEngineStateFree(DetectEngineState *state)
Frees a DetectEngineState object.
Definition: detect-engine-state.c:173
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:251
AppLayerParserRegisterGetTx
void AppLayerParserRegisterGetTx(uint8_t ipproto, AppProto alproto, void *(StateGetTx)(void *alstate, uint64_t tx_id))
Definition: app-layer-parser.c:507
FtpState_::current_line
const uint8_t * current_line
Definition: app-layer-ftp.h:174
util-mem.h
APP_LAYER_OK
#define APP_LAYER_OK
Definition: app-layer-parser.h:86
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:1963
SCReturnStruct
#define SCReturnStruct(x)
Definition: util-debug.h:320
FTPTransaction_::request_length
uint32_t request_length
Definition: app-layer-ftp.h:141
FAIL_IF
#define FAIL_IF(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:71
util-mpm.h
StreamTcpFreeConfig
void StreamTcpFreeConfig(bool quiet)
Definition: stream-tcp.c:670
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:1211
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:176
FTPTransaction_::de_state
DetectEngineState * de_state
Definition: app-layer-ftp.h:156
FtpState_::port_line_len
uint32_t port_line_len
Definition: app-layer-ftp.h:184
FtpState_::dyn_port
uint16_t dyn_port
Definition: app-layer-ftp.h:188
TAILQ_NEXT
#define TAILQ_NEXT(elm, field)
Definition: queue.h:341
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:125
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:499
AppLayerParserRegisterTxDataFunc
void AppLayerParserRegisterTxDataFunc(uint8_t ipproto, AppProto alproto, AppLayerTxData *(*GetTxData)(void *tx))
Definition: app-layer-parser.c:577
FTPAtExitPrintStats
void FTPAtExitPrintStats(void)
Definition: app-layer-ftp.c:1363
Flow_::parent_id
int64_t parent_id
Definition: flow.h:440
FTP_COMMAND_MRCP
@ FTP_COMMAND_MRCP
Definition: app-layer-ftp.h:56
FtpDataState_
Definition: app-layer-ftp.h:200
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:268
MpmTableElmt_::DestroyCtx
void(* DestroyCtx)(struct MpmCtx_ *)
Definition: util-mpm.h:148
FlowFreeStorageById
void FlowFreeStorageById(Flow *f, FlowStorageId id)
Definition: flow-storage.c:54
SCFree
#define SCFree(p)
Definition: util-mem.h:61
Flow_::alstate
void * alstate
Definition: flow.h:486
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
FtpState_::tx_cnt
uint64_t tx_cnt
Definition: app-layer-ftp.h:170
EveFTPDataAddMetadata
void EveFTPDataAddMetadata(const Flow *f, JsonBuilder *jb)
Definition: app-layer-ftp.c:1401
FtpDataState_::de_state
DetectEngineState * de_state
Definition: app-layer-ftp.h:204
STREAM_EOF
#define STREAM_EOF
Definition: stream.h:30
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:496
APP_LAYER_ERROR
#define APP_LAYER_ERROR
Definition: app-layer-parser.h:90
FtpState_::port_line_size
uint32_t port_line_size
Definition: app-layer-ftp.h:185
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:147
FTPTransaction_::active
bool active
Definition: app-layer-ftp.h:149
FILE_USE_DETECT
#define FILE_USE_DETECT
Definition: util-file.h:58
FTP_COMMAND_STOR
@ FTP_COMMAND_STOR
Definition: app-layer-ftp.h:78
FtpDataState_::files
FileContainer * files
Definition: app-layer-ftp.h:203
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:149
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:462
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:376
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:1391
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:460
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:177
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:250
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:1987
FileCloseFile
int FileCloseFile(FileContainer *ffc, const uint8_t *data, uint32_t data_len, uint16_t flags)
Close a File.
Definition: util-file.c:1008
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
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:202
FTP_COMMAND_MLFL
@ FTP_COMMAND_MLFL
Definition: app-layer-ftp.h:54
FtpTransferCmd::file_name
uint8_t * file_name
Definition: app-layer-ftp.c:501
app-layer.h
PrefilterRuleStore_::rule_id_array
SigIntId * rule_id_array
Definition: util-prefilter.h:36