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) {
1058  if (data == NULL) {
1060  }
1061 
1062  ftpdata_state->files = FileContainerAlloc();
1063  if (ftpdata_state->files == NULL) {
1066  }
1067 
1068  ftpdata_state->file_name = data->file_name;
1069  ftpdata_state->file_len = data->file_len;
1070  data->file_name = NULL;
1071  data->file_len = 0;
1072  f->parent_id = data->flow_id;
1073  ftpdata_state->command = data->cmd;
1074  switch (data->cmd) {
1075  case FTP_COMMAND_STOR:
1076  ftpdata_state->direction = STREAM_TOSERVER;
1077  break;
1078  case FTP_COMMAND_RETR:
1079  ftpdata_state->direction = STREAM_TOCLIENT;
1080  break;
1081  default:
1082  break;
1083  }
1084 
1085  /* open with fixed track_id 0 as we can have just one
1086  * file per ftp-data flow. */
1087  if (FileOpenFileWithId(ftpdata_state->files, &sbcfg,
1088  0ULL, (uint8_t *) ftpdata_state->file_name,
1089  ftpdata_state->file_len,
1090  input, input_len, flags) != 0) {
1091  SCLogDebug("Can't open file");
1092  ret = -1;
1093  }
1095  } else {
1096  if (input_len != 0) {
1097  ret = FileAppendData(ftpdata_state->files, input, input_len);
1098  if (ret == -2) {
1099  ret = 0;
1100  SCLogDebug("FileAppendData() - file no longer being extracted");
1101  goto out;
1102  } else if (ret < 0) {
1103  SCLogDebug("FileAppendData() failed: %d", ret);
1104  ret = -2;
1105  goto out;
1106  }
1107  } else {
1108  ret = FileCloseFile(ftpdata_state->files, NULL, 0, flags);
1109  ftpdata_state->state = FTPDATA_STATE_FINISHED;
1110  if (ret < 0)
1111  goto out;
1112  }
1113  }
1114 
1115  const bool eof_flag = flags & STREAM_TOSERVER ?
1118  if (input_len && eof_flag) {
1119  ret = FileCloseFile(ftpdata_state->files, (uint8_t *) NULL, 0, flags);
1120  ftpdata_state->state = FTPDATA_STATE_FINISHED;
1121  }
1122 
1123 out:
1124  if (ret < 0) {
1126  }
1128 }
1129 
1130 static AppLayerResult FTPDataParseRequest(Flow *f, void *ftp_state,
1131  AppLayerParserState *pstate,
1132  const uint8_t *input, uint32_t input_len,
1133  void *local_data, const uint8_t flags)
1134 {
1135  return FTPDataParse(f, ftp_state, pstate, input, input_len,
1136  local_data, STREAM_TOSERVER);
1137 }
1138 
1139 static AppLayerResult FTPDataParseResponse(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_TOCLIENT);
1146 }
1147 
1148 #ifdef DEBUG
1149 static SCMutex ftpdata_state_mem_lock = SCMUTEX_INITIALIZER;
1150 static uint64_t ftpdata_state_memuse = 0;
1151 static uint64_t ftpdata_state_memcnt = 0;
1152 #endif
1153 
1154 static void *FTPDataStateAlloc(void *orig_state, AppProto proto_orig)
1155 {
1156  void *s = FTPCalloc(1, sizeof(FtpDataState));
1157  if (unlikely(s == NULL))
1158  return NULL;
1159 
1160  FtpDataState *state = (FtpDataState *) s;
1162 
1163 #ifdef DEBUG
1164  SCMutexLock(&ftpdata_state_mem_lock);
1165  ftpdata_state_memcnt++;
1166  ftpdata_state_memuse+=sizeof(FtpDataState);
1167  SCMutexUnlock(&ftpdata_state_mem_lock);
1168 #endif
1169  return s;
1170 }
1171 
1172 static void FTPDataStateFree(void *s)
1173 {
1174  FtpDataState *fstate = (FtpDataState *) s;
1175 
1176  if (fstate->de_state != NULL) {
1178  }
1179  if (fstate->file_name != NULL) {
1180  FTPFree(fstate->file_name, fstate->file_len + 1);
1181  }
1182 
1183  FileContainerFree(fstate->files);
1184 
1185  FTPFree(s, sizeof(FtpDataState));
1186 #ifdef DEBUG
1187  SCMutexLock(&ftpdata_state_mem_lock);
1188  ftpdata_state_memcnt--;
1189  ftpdata_state_memuse-=sizeof(FtpDataState);
1190  SCMutexUnlock(&ftpdata_state_mem_lock);
1191 #endif
1192 }
1193 
1194 static int FTPDataSetTxDetectState(void *vtx, DetectEngineState *de_state)
1195 {
1196  FtpDataState *ftp_state = (FtpDataState *)vtx;
1197  ftp_state->de_state = de_state;
1198  return 0;
1199 }
1200 
1201 static DetectEngineState *FTPDataGetTxDetectState(void *vtx)
1202 {
1203  FtpDataState *ftp_state = (FtpDataState *)vtx;
1204  return ftp_state->de_state;
1205 }
1206 
1207 static AppLayerTxData *FTPDataGetTxData(void *vtx)
1208 {
1209  FtpDataState *ftp_state = (FtpDataState *)vtx;
1210  return &ftp_state->tx_data;
1211 }
1212 
1213 static void FTPDataStateTransactionFree(void *state, uint64_t tx_id)
1214 {
1215  /* do nothing */
1216 }
1217 
1218 static void *FTPDataGetTx(void *state, uint64_t tx_id)
1219 {
1220  FtpDataState *ftp_state = (FtpDataState *)state;
1221  return ftp_state;
1222 }
1223 
1224 static uint64_t FTPDataGetTxCnt(void *state)
1225 {
1226  /* ftp-data is single tx */
1227  return 1;
1228 }
1229 
1230 static int FTPDataGetAlstateProgress(void *tx, uint8_t direction)
1231 {
1232  FtpDataState *ftpdata_state = (FtpDataState *)tx;
1233  return ftpdata_state->state;
1234 }
1235 
1236 static FileContainer *FTPDataStateGetFiles(void *state, uint8_t direction)
1237 {
1238  FtpDataState *ftpdata_state = (FtpDataState *)state;
1239 
1240  if (direction != ftpdata_state->direction)
1241  SCReturnPtr(NULL, "FileContainer");
1242 
1243  SCReturnPtr(ftpdata_state->files, "FileContainer");
1244 }
1245 
1246 static void FTPSetMpmState(void)
1247 {
1248  ftp_mpm_ctx = SCMalloc(sizeof(MpmCtx));
1249  if (unlikely(ftp_mpm_ctx == NULL)) {
1250  exit(EXIT_FAILURE);
1251  }
1252  memset(ftp_mpm_ctx, 0, sizeof(MpmCtx));
1253  MpmInitCtx(ftp_mpm_ctx, FTP_MPM);
1254 
1255  uint32_t i = 0;
1256  for (i = 0; i < sizeof(FtpCommands)/sizeof(FtpCommand) - 1; i++) {
1257  const FtpCommand *cmd = &FtpCommands[i];
1258  if (cmd->command_length == 0)
1259  continue;
1260 
1261  MpmAddPatternCI(ftp_mpm_ctx,
1262  (uint8_t *)cmd->command_name,
1263  cmd->command_length,
1264  0 /* defunct */, 0 /* defunct */,
1265  i /* id */, i /* rule id */ , 0 /* no flags */);
1266  }
1267 
1268  mpm_table[FTP_MPM].Prepare(ftp_mpm_ctx);
1269 
1270 }
1271 
1272 static void FTPFreeMpmState(void)
1273 {
1274  if (ftp_mpm_ctx != NULL) {
1275  mpm_table[FTP_MPM].DestroyCtx(ftp_mpm_ctx);
1276  SCFree(ftp_mpm_ctx);
1277  ftp_mpm_ctx = NULL;
1278  }
1279 }
1280 
1282 {
1283  const char *proto_name = "ftp";
1284  const char *proto_data_name = "ftp-data";
1285 
1286  /** FTP */
1287  if (AppLayerProtoDetectConfProtoDetectionEnabled("tcp", proto_name)) {
1289  if (FTPRegisterPatternsForProtocolDetection() < 0 )
1290  return;
1292  }
1293 
1294  if (AppLayerParserConfParserEnabled("tcp", proto_name)) {
1296  FTPParseRequest);
1298  FTPParseResponse);
1299  AppLayerParserRegisterStateFuncs(IPPROTO_TCP, ALPROTO_FTP, FTPStateAlloc, FTPStateFree);
1301 
1302  AppLayerParserRegisterTxFreeFunc(IPPROTO_TCP, ALPROTO_FTP, FTPStateTransactionFree);
1303 
1305  FTPGetTxDetectState, FTPSetTxDetectState);
1306 
1307  AppLayerParserRegisterGetTx(IPPROTO_TCP, ALPROTO_FTP, FTPGetTx);
1308  AppLayerParserRegisterTxDataFunc(IPPROTO_TCP, ALPROTO_FTP, FTPGetTxData);
1309 
1310  AppLayerParserRegisterLocalStorageFunc(IPPROTO_TCP, ALPROTO_FTP, FTPLocalStorageAlloc,
1311  FTPLocalStorageFree);
1312  AppLayerParserRegisterGetTxCnt(IPPROTO_TCP, ALPROTO_FTP, FTPGetTxCnt);
1313 
1314  AppLayerParserRegisterGetStateProgressFunc(IPPROTO_TCP, ALPROTO_FTP, FTPGetAlstateProgress);
1315 
1318 
1321  FTPDataParseRequest);
1323  FTPDataParseResponse);
1324  AppLayerParserRegisterStateFuncs(IPPROTO_TCP, ALPROTO_FTPDATA, FTPDataStateAlloc, FTPDataStateFree);
1326  AppLayerParserRegisterTxFreeFunc(IPPROTO_TCP, ALPROTO_FTPDATA, FTPDataStateTransactionFree);
1328  FTPDataGetTxDetectState, FTPDataSetTxDetectState);
1329 
1330  AppLayerParserRegisterGetFilesFunc(IPPROTO_TCP, ALPROTO_FTPDATA, FTPDataStateGetFiles);
1331 
1332  AppLayerParserRegisterGetTx(IPPROTO_TCP, ALPROTO_FTPDATA, FTPDataGetTx);
1333  AppLayerParserRegisterTxDataFunc(IPPROTO_TCP, ALPROTO_FTPDATA, FTPDataGetTxData);
1334 
1335  AppLayerParserRegisterGetTxCnt(IPPROTO_TCP, ALPROTO_FTPDATA, FTPDataGetTxCnt);
1336 
1337  AppLayerParserRegisterGetStateProgressFunc(IPPROTO_TCP, ALPROTO_FTPDATA, FTPDataGetAlstateProgress);
1338 
1341 
1342  sbcfg.buf_size = 4096;
1343  sbcfg.Malloc = FTPMalloc;
1344  sbcfg.Calloc = FTPCalloc;
1345  sbcfg.Realloc = FTPRealloc;
1346  sbcfg.Free = FTPFree;
1347 
1348  FTPParseMemcap();
1349  } else {
1350  SCLogInfo("Parsed disabled for %s protocol. Protocol detection"
1351  "still on.", proto_name);
1352  }
1353 
1354  FTPSetMpmState();
1355 
1356 #ifdef UNITTESTS
1358 #endif
1359 }
1360 
1362 {
1363 #ifdef DEBUG
1364  SCMutexLock(&ftp_state_mem_lock);
1365  SCLogDebug("ftp_state_memcnt %"PRIu64", ftp_state_memuse %"PRIu64"",
1366  ftp_state_memcnt, ftp_state_memuse);
1367  SCMutexUnlock(&ftp_state_mem_lock);
1368 #endif
1369 }
1370 
1371 
1372 /*
1373  * \brief Returns the ending offset of the next line from a multi-line buffer.
1374  *
1375  * "Buffer" refers to a FTP response in a single buffer containing multiple lines.
1376  * Here, "next line" is defined as terminating on
1377  * - Newline character
1378  * - Null character
1379  *
1380  * \param buffer Contains zero or more characters.
1381  * \param len Size, in bytes, of buffer.
1382  *
1383  * \retval Offset from the start of buffer indicating the where the
1384  * next "line ends". The characters between the input buffer and this
1385  * value comprise the line.
1386  *
1387  * NULL is found first or a newline isn't found, then UINT16_MAX is returned.
1388  */
1389 uint16_t JsonGetNextLineFromBuffer(const char *buffer, const uint16_t len)
1390 {
1391  if (!buffer || *buffer == '\0') {
1392  return UINT16_MAX;
1393  }
1394 
1395  char *c = strchr(buffer, '\n');
1396  return c == NULL ? len : c - buffer + 1;
1397 }
1398 
1399 void EveFTPDataAddMetadata(const Flow *f, JsonBuilder *jb)
1400 {
1401  const FtpDataState *ftp_state = NULL;
1402  if (f->alstate == NULL)
1403  return;
1404 
1405  ftp_state = (FtpDataState *)f->alstate;
1406 
1407  if (ftp_state->file_name) {
1408  jb_set_string_from_bytes(jb, "filename", ftp_state->file_name, ftp_state->file_len);
1409  }
1410  switch (ftp_state->command) {
1411  case FTP_COMMAND_STOR:
1412  JB_SET_STRING(jb, "command", "STOR");
1413  break;
1414  case FTP_COMMAND_RETR:
1415  JB_SET_STRING(jb, "command", "RETR");
1416  break;
1417  default:
1418  break;
1419  }
1420 }
1421 
1422 /**
1423  * \brief Free memory allocated for global FTP parser state.
1424  */
1426 {
1427  FTPFreeMpmState();
1428 }
1429 
1430 /* UNITTESTS */
1431 #ifdef UNITTESTS
1432 
1433 /** \test Send a get request in one chunk. */
1434 static int FTPParserTest01(void)
1435 {
1436  Flow f;
1437  uint8_t ftpbuf[] = "PORT 192,168,1,1,0,80\r\n";
1438  uint32_t ftplen = sizeof(ftpbuf) - 1; /* minus the \0 */
1439  TcpSession ssn;
1441 
1442  memset(&f, 0, sizeof(f));
1443  memset(&ssn, 0, sizeof(ssn));
1444 
1445  f.protoctx = (void *)&ssn;
1446  f.proto = IPPROTO_TCP;
1447  f.alproto = ALPROTO_FTP;
1448 
1450 
1451  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_FTP,
1452  STREAM_TOSERVER | STREAM_EOF, ftpbuf, ftplen);
1453  FAIL_IF(r != 0);
1454 
1455  FtpState *ftp_state = f.alstate;
1456  FAIL_IF_NULL(ftp_state);
1457  FAIL_IF(ftp_state->command != FTP_COMMAND_PORT);
1458 
1461  PASS;
1462 }
1463 
1464 /** \test Send a split get request. */
1465 static int FTPParserTest03(void)
1466 {
1467  Flow f;
1468  uint8_t ftpbuf1[] = "POR";
1469  uint32_t ftplen1 = sizeof(ftpbuf1) - 1; /* minus the \0 */
1470  uint8_t ftpbuf2[] = "T 192,168,1";
1471  uint32_t ftplen2 = sizeof(ftpbuf2) - 1; /* minus the \0 */
1472  uint8_t ftpbuf3[] = "1,1,10,20\r\n";
1473  uint32_t ftplen3 = sizeof(ftpbuf3) - 1; /* minus the \0 */
1474  TcpSession ssn;
1476 
1477  memset(&f, 0, sizeof(f));
1478  memset(&ssn, 0, sizeof(ssn));
1479 
1480  f.protoctx = (void *)&ssn;
1481  f.proto = IPPROTO_TCP;
1482  f.alproto = ALPROTO_FTP;
1483 
1485 
1486  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_FTP,
1487  STREAM_TOSERVER | STREAM_START, ftpbuf1,
1488  ftplen1);
1489  FAIL_IF(r != 0);
1490 
1492  ftpbuf2, ftplen2);
1493  FAIL_IF(r != 0);
1494 
1495  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_FTP,
1496  STREAM_TOSERVER | STREAM_EOF, ftpbuf3, ftplen3);
1497  FAIL_IF(r != 0);
1498 
1499  FtpState *ftp_state = f.alstate;
1500  FAIL_IF_NULL(ftp_state);
1501 
1502  FAIL_IF(ftp_state->command != FTP_COMMAND_PORT);
1503 
1506  PASS;
1507 }
1508 
1509 /** \test See how it deals with an incomplete request. */
1510 static int FTPParserTest06(void)
1511 {
1512  Flow f;
1513  uint8_t ftpbuf1[] = "PORT";
1514  uint32_t ftplen1 = sizeof(ftpbuf1) - 1; /* minus the \0 */
1515  TcpSession ssn;
1517 
1518  memset(&f, 0, sizeof(f));
1519  memset(&ssn, 0, sizeof(ssn));
1520 
1521  f.protoctx = (void *)&ssn;
1522  f.proto = IPPROTO_TCP;
1523  f.alproto = ALPROTO_FTP;
1524 
1526 
1527  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_FTP,
1529  ftpbuf1,
1530  ftplen1);
1531  FAIL_IF(r != 0);
1532 
1533  FtpState *ftp_state = f.alstate;
1534  FAIL_IF_NULL(ftp_state);
1535 
1536  FAIL_IF(ftp_state->command != FTP_COMMAND_UNKNOWN);
1537 
1540  PASS;
1541 }
1542 
1543 /** \test See how it deals with an incomplete request in multiple chunks. */
1544 static int FTPParserTest07(void)
1545 {
1546  Flow f;
1547  uint8_t ftpbuf1[] = "PO";
1548  uint32_t ftplen1 = sizeof(ftpbuf1) - 1; /* minus the \0 */
1549  uint8_t ftpbuf2[] = "RT\r\n";
1550  uint32_t ftplen2 = sizeof(ftpbuf2) - 1; /* minus the \0 */
1551  TcpSession ssn;
1553 
1554  memset(&f, 0, sizeof(f));
1555  memset(&ssn, 0, sizeof(ssn));
1556 
1557  f.protoctx = (void *)&ssn;
1558  f.proto = IPPROTO_TCP;
1559  f.alproto = ALPROTO_FTP;
1560 
1562 
1563  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_FTP,
1564  STREAM_TOSERVER | STREAM_START, ftpbuf1,
1565  ftplen1);
1566  FAIL_IF(r != 0);
1567 
1568  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_FTP,
1569  STREAM_TOSERVER | STREAM_EOF, ftpbuf2, ftplen2);
1570  FAIL_IF(r != 0);
1571 
1572  FtpState *ftp_state = f.alstate;
1573  FAIL_IF_NULL(ftp_state);
1574 
1575  FAIL_IF(ftp_state->command != FTP_COMMAND_PORT);
1576 
1579  PASS;
1580 }
1581 
1582 /** \test Test case where chunks are smaller than the delim length and the
1583  * last chunk is supposed to match the delim. */
1584 static int FTPParserTest10(void)
1585 {
1586  Flow f;
1587  uint8_t ftpbuf1[] = "PORT 1,2,3,4,5,6\r\n";
1588  uint32_t ftplen1 = sizeof(ftpbuf1) - 1; /* minus the \0 */
1589  TcpSession ssn;
1591  int r = 0;
1592  memset(&f, 0, sizeof(f));
1593  memset(&ssn, 0, sizeof(ssn));
1594 
1595  f.protoctx = (void *)&ssn;
1596  f.proto = IPPROTO_TCP;
1597  f.alproto = ALPROTO_FTP;
1598 
1600 
1601  uint32_t u;
1602  for (u = 0; u < ftplen1; u++) {
1603  uint8_t flags = 0;
1604 
1605  if (u == 0) flags = STREAM_TOSERVER|STREAM_START;
1606  else if (u == (ftplen1 - 1)) flags = STREAM_TOSERVER|STREAM_EOF;
1607  else flags = STREAM_TOSERVER;
1608 
1610  &ftpbuf1[u], 1);
1611  FAIL_IF(r != 0);
1612  }
1613 
1614  FtpState *ftp_state = f.alstate;
1615  FAIL_IF_NULL(ftp_state);
1616 
1617  FAIL_IF(ftp_state->command != FTP_COMMAND_PORT);
1618 
1621  PASS;
1622 }
1623 
1624 /** \test Supply RETR without a filename */
1625 static int FTPParserTest11(void)
1626 {
1627  Flow f;
1628  uint8_t ftpbuf1[] = "PORT 192,168,1,1,0,80\r\n";
1629  uint8_t ftpbuf2[] = "RETR\r\n";
1630  uint8_t ftpbuf3[] = "227 OK\r\n";
1631  TcpSession ssn;
1632 
1634 
1635  memset(&f, 0, sizeof(f));
1636  memset(&ssn, 0, sizeof(ssn));
1637 
1638  f.protoctx = (void *)&ssn;
1639  f.proto = IPPROTO_TCP;
1640  f.alproto = ALPROTO_FTP;
1641 
1643 
1644  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_FTP,
1645  STREAM_TOSERVER | STREAM_START, ftpbuf1,
1646  sizeof(ftpbuf1) - 1);
1647  FAIL_IF(r != 0);
1648 
1649  /* Response */
1650  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_FTP,
1652  ftpbuf3,
1653  sizeof(ftpbuf3) - 1);
1654  FAIL_IF(r != 0);
1655 
1656  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_FTP,
1657  STREAM_TOSERVER, ftpbuf2,
1658  sizeof(ftpbuf2) - 1);
1659  FAIL_IF(r == 0);
1660 
1661  FtpState *ftp_state = f.alstate;
1662  FAIL_IF_NULL(ftp_state);
1663 
1664  FAIL_IF(ftp_state->command != FTP_COMMAND_RETR);
1665 
1668  PASS;
1669 }
1670 
1671 /** \test Supply STOR without a filename */
1672 static int FTPParserTest12(void)
1673 {
1674  Flow f;
1675  uint8_t ftpbuf1[] = "PORT 192,168,1,1,0,80\r\n";
1676  uint8_t ftpbuf2[] = "STOR\r\n";
1677  uint8_t ftpbuf3[] = "227 OK\r\n";
1678  TcpSession ssn;
1679 
1681 
1682  memset(&f, 0, sizeof(f));
1683  memset(&ssn, 0, sizeof(ssn));
1684 
1685  f.protoctx = (void *)&ssn;
1686  f.proto = IPPROTO_TCP;
1687  f.alproto = ALPROTO_FTP;
1688 
1690 
1691  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_FTP,
1692  STREAM_TOSERVER | STREAM_START, ftpbuf1,
1693  sizeof(ftpbuf1) - 1);
1694  FAIL_IF(r != 0);
1695 
1696  /* Response */
1697  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_FTP,
1699  ftpbuf3,
1700  sizeof(ftpbuf3) - 1);
1701  FAIL_IF(r != 0);
1702 
1703  r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_FTP,
1704  STREAM_TOSERVER, ftpbuf2,
1705  sizeof(ftpbuf2) - 1);
1706  FAIL_IF(r == 0);
1707 
1708  FtpState *ftp_state = f.alstate;
1709  FAIL_IF_NULL(ftp_state);
1710 
1711  FAIL_IF(ftp_state->command != FTP_COMMAND_STOR);
1712 
1715  PASS;
1716 }
1717 #endif /* UNITTESTS */
1718 
1720 {
1721 #ifdef UNITTESTS
1722  UtRegisterTest("FTPParserTest01", FTPParserTest01);
1723  UtRegisterTest("FTPParserTest03", FTPParserTest03);
1724  UtRegisterTest("FTPParserTest06", FTPParserTest06);
1725  UtRegisterTest("FTPParserTest07", FTPParserTest07);
1726  UtRegisterTest("FTPParserTest10", FTPParserTest10);
1727  UtRegisterTest("FTPParserTest11", FTPParserTest11);
1728  UtRegisterTest("FTPParserTest12", FTPParserTest12);
1729 #endif /* UNITTESTS */
1730 }
1731 
MpmInitThreadCtx
void MpmInitThreadCtx(MpmThreadCtx *mpm_thread_ctx, uint16_t matcher)
Definition: util-mpm.c:256
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:476
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:1784
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:412
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
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:261
FTP_COMMAND_RNFR
@ FTP_COMMAND_RNFR
Definition: app-layer-ftp.h:72
Flow_::proto
uint8_t proto
Definition: flow.h:369
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:302
FTP_STATE_PORT_DONE
@ FTP_STATE_PORT_DONE
Definition: app-layer-ftp.h:32
STREAMING_BUFFER_CONFIG_INITIALIZER
#define STREAMING_BUFFER_CONFIG_INITIALIZER
Definition: util-streaming-buffer.h:77
FtpLineState_::current_line_db
uint8_t current_line_db
Definition: app-layer-ftp.h:123
threads.h
Flow_
Flow data structure.
Definition: flow.h:347
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:528
AppLayerParserRegisterParserAcceptableDataDirection
void AppLayerParserRegisterParserAcceptableDataDirection(uint8_t ipproto, AppProto alproto, uint8_t direction)
Definition: app-layer-parser.c:372
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:487
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:279
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:567
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
AppLayerExpectationGetDataId
int AppLayerExpectationGetDataId(void)
Definition: app-layer-expectation.c:287
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:445
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:1425
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
AppLayerParserStateIssetFlag
int AppLayerParserStateIssetFlag(AppLayerParserState *pstate, uint8_t flag)
Definition: app-layer-parser.c:1672
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:155
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:19
AppLayerParserRegisterGetFilesFunc
void AppLayerParserRegisterGetFilesFunc(uint8_t ipproto, AppProto alproto, FileContainer *(*StateGetFiles)(void *, uint8_t))
Definition: app-layer-parser.c:426
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:399
app-layer-parser.h
TRUE
#define TRUE
Definition: suricata-common.h:33
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:1719
RegisterFTPParsers
void RegisterFTPParsers(void)
Definition: app-layer-ftp.c:1281
stream.h
AppLayerParserRegisterProtocolUnittests
void AppLayerParserRegisterProtocolUnittests(uint8_t ipproto, AppProto alproto, void(*RegisterUnittests)(void))
Definition: app-layer-parser.c:1770
AppLayerExpectationCreate
int AppLayerExpectationCreate(Flow *f, int direction, Port src, Port dst, AppProto alproto, void *data)
Definition: app-layer-expectation.c:218
FtpCommand_
Definition: app-layer-ftp.h:92
StreamTcpFreeConfig
void StreamTcpFreeConfig(char quiet)
Definition: stream-tcp.c:670
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:2139
MpmTableElmt_::Prepare
int(* Prepare)(struct MpmCtx_ *)
Definition: util-mpm.h:163
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:1859
FtpDataState
struct FtpDataState_ FtpDataState
FTP_COMMAND_ACCT
@ FTP_COMMAND_ACCT
Definition: app-layer-ftp.h:39
FTPMemcapGlobalCounter
uint64_t FTPMemcapGlobalCounter(void)
Definition: app-layer-ftp.c:175
MpmTableElmt_::Search
uint32_t(* Search)(const struct MpmCtx_ *, struct MpmThreadCtx_ *, PrefilterRuleStore *, const uint8_t *, uint32_t)
Definition: util-mpm.h:164
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:360
DetectEngineStateFree
void DetectEngineStateFree(DetectEngineState *state)
Frees a DetectEngineState object.
Definition: detect-engine-state.c:174
SCRealloc
#define SCRealloc(ptr, sz)
Definition: util-mem.h:50
AppLayerParserThreadCtxAlloc
AppLayerParserThreadCtx * AppLayerParserThreadCtxAlloc(void)
Gets a new app layer protocol's parser thread context.
Definition: app-layer-parser.c:253
AppLayerParserRegisterGetTx
void AppLayerParserRegisterGetTx(uint8_t ipproto, AppProto alproto, void *(StateGetTx)(void *alstate, uint64_t tx_id))
Definition: app-layer-parser.c:509
FtpState_::current_line
const uint8_t * current_line
Definition: app-layer-ftp.h:174
util-mem.h
length
uint16_t length
Definition: app-layer-modbus.c:2
APP_LAYER_OK
#define APP_LAYER_OK
Definition: app-layer-parser.h:60
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:1907
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
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:1226
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:579
FTPAtExitPrintStats
void FTPAtExitPrintStats(void)
Definition: app-layer-ftp.c:1361
Flow_::parent_id
int64_t parent_id
Definition: flow.h:434
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:147
SCFree
#define SCFree(p)
Definition: util-mem.h:61
Flow_::alstate
void * alstate
Definition: flow.h:480
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:1399
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:204
STREAM_EOF
#define STREAM_EOF
Definition: stream.h:30
FlowGetStorageById
void * FlowGetStorageById(Flow *f, int id)
Definition: flow-storage.c:39
mpm_table
MpmTableElmt mpm_table[MPM_TABLE_SIZE]
Definition: util-mpm.c:48
app-layer-protos.h
FTP_COMMAND_IDLE
@ FTP_COMMAND_IDLE
Definition: app-layer-ftp.h:49
AppLayerParserRegisterGetTxCnt
void AppLayerParserRegisterGetTxCnt(uint8_t ipproto, AppProto alproto, uint64_t(*StateGetTxCnt)(void *alstate))
Definition: app-layer-parser.c:498
APP_LAYER_ERROR
#define APP_LAYER_ERROR
Definition: app-layer-parser.h:64
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:148
AppLayerParserThreadCtx_
Definition: app-layer-parser.c:87
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:1389
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:454
FlowFreeStorageById
void FlowFreeStorageById(Flow *f, int id)
Definition: flow-storage.c:54
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
FTP_COMMAND_REST
@ FTP_COMMAND_REST
Definition: app-layer-ftp.h:69
util-pool.h
FTP_STATE_IN_PROGRESS
@ FTP_STATE_IN_PROGRESS
Definition: app-layer-ftp.h:31
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:304
FtpState_::current_line_delimiter_len
uint8_t current_line_delimiter_len
Definition: app-layer-ftp.h: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:311
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:1931
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