]> git.ipfire.org Git - people/ms/suricata.git/blame - src/output-json-ftp.c
core: Remove unneeded consts
[people/ms/suricata.git] / src / output-json-ftp.c
CommitLineData
2d78afe4 1/* Copyright (C) 2017-2021 Open Information Security Foundation
1930b1f5
JL
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 Jeff Lucovsky <jeff@lucovsky.org>
22 *
23 * Implement JSON/eve logging app-layer FTP.
24 */
25
26
27#include "suricata-common.h"
28#include "debug.h"
29#include "detect.h"
30#include "pkt-var.h"
31#include "conf.h"
32
33#include "threads.h"
34#include "threadvars.h"
35#include "tm-threads.h"
36
37#include "util-unittest.h"
38#include "util-buffer.h"
39#include "util-debug.h"
66c565e9 40#include "util-mem.h"
1930b1f5
JL
41
42#include "output.h"
43#include "output-json.h"
44
45#include "app-layer.h"
46#include "app-layer-parser.h"
47
48#include "app-layer-ftp.h"
49#include "output-json-ftp.h"
50
648bd5af 51static void EveFTPLogCommand(Flow *f, FTPTransaction *tx, JsonBuilder *jb)
1930b1f5 52{
9cf4e2e4 53 /* Preallocate array objects to simplify failure case */
03de315b 54 JsonBuilder *js_resplist = NULL;
9cf4e2e4 55 if (!TAILQ_EMPTY(&tx->response_list)) {
03de315b 56 js_resplist = jb_new_array();
9cf4e2e4 57
1f19ab10 58 if (unlikely(js_resplist == NULL)) {
bd22e0d7 59 return;
9cf4e2e4
JL
60 }
61 }
03de315b 62 jb_set_string(jb, "command", tx->command_descriptor->command_name);
9cf4e2e4
JL
63 uint32_t min_length = tx->command_descriptor->command_length + 1; /* command + space */
64 if (tx->request_length > min_length) {
03de315b
JL
65 jb_set_string_from_bytes(jb,
66 "command_data",
67 (const uint8_t *)tx->request + min_length,
68 tx->request_length - min_length - 1);
9cf4e2e4
JL
69 }
70
71 if (!TAILQ_EMPTY(&tx->response_list)) {
03de315b
JL
72 int resp_code_cnt = 0;
73 int resp_cnt = 0;
9cf4e2e4 74 FTPString *response;
1f19ab10 75 bool is_cc_array_open = false;
9cf4e2e4 76 TAILQ_FOREACH(response, &tx->response_list, next) {
66c565e9
JL
77 /* handle multiple lines within the response, \r\n delimited */
78 uint8_t *where = response->str;
aa3f784d 79 uint16_t length = response->len ? response->len -1 : 0;
66c565e9
JL
80 uint16_t pos;
81 while ((pos = JsonGetNextLineFromBuffer((const char *)where, length)) != UINT16_MAX) {
82 uint16_t offset = 0;
83 /* Try to find a completion code for this line */
84 if (pos >= 3) {
85 /* Gather the completion code if present */
86 if (isdigit(where[0]) && isdigit(where[1]) && isdigit(where[2])) {
1f19ab10
JL
87 if (!is_cc_array_open) {
88 jb_open_array(jb, "completion_code");
89 is_cc_array_open = true;
90 }
91 jb_append_string_from_bytes(jb, (const uint8_t *)where, 3);
03de315b 92 resp_code_cnt++;
66c565e9
JL
93 offset = 4;
94 }
1930b1f5 95 }
66c565e9
JL
96 /* move past 3 character completion code */
97 if (pos >= offset) {
03de315b
JL
98 jb_append_string_from_bytes(js_resplist, (const uint8_t *)where + offset, pos - offset);
99 resp_cnt++;
66c565e9
JL
100 }
101
102 where += pos;
103 length -= pos;
1930b1f5
JL
104 }
105 }
9cf4e2e4 106
1f19ab10
JL
107 if (is_cc_array_open) {
108 jb_close(jb);
109 }
03de315b
JL
110 if (resp_cnt) {
111 jb_close(js_resplist);
112 jb_set_object(jb, "reply", js_resplist);
113 }
114 jb_free(js_resplist);
9cf4e2e4
JL
115 }
116
117 if (tx->dyn_port) {
03de315b 118 jb_set_uint(jb, "dynamic_port", tx->dyn_port);
1930b1f5
JL
119 }
120
9cf4e2e4
JL
121 if (tx->command_descriptor->command == FTP_COMMAND_PORT ||
122 tx->command_descriptor->command == FTP_COMMAND_EPRT) {
03de315b
JL
123 if (tx->active) {
124 JB_SET_STRING(jb, "mode", "active");
125 } else {
126 JB_SET_STRING(jb, "mode", "passive");
127 }
128 }
129
130 if (tx->done) {
131 JB_SET_STRING(jb, "reply_received", "yes");
132 } else {
133 JB_SET_STRING(jb, "reply_received", "no");
1930b1f5
JL
134 }
135}
136
9cf4e2e4 137
1930b1f5
JL
138static int JsonFTPLogger(ThreadVars *tv, void *thread_data,
139 const Packet *p, Flow *f, void *state, void *vtx, uint64_t tx_id)
140{
141 SCEnter();
67c4621b 142 OutputJsonThreadCtx *thread = thread_data;
1930b1f5 143
9cf4e2e4
JL
144 const char *event_type;
145 if (f->alproto == ALPROTO_FTPDATA) {
146 event_type = "ftp_data";
147 } else {
148 event_type = "ftp";
149 }
1930b1f5 150 FTPTransaction *tx = vtx;
1930b1f5 151
67c4621b
JI
152 JsonBuilder *jb =
153 CreateEveHeaderWithTxId(p, LOG_DIR_FLOW, event_type, NULL, tx_id, thread->ctx);
03de315b 154 if (likely(jb)) {
03de315b 155 jb_open_object(jb, event_type);
9cf4e2e4 156 if (f->alproto == ALPROTO_FTPDATA) {
648bd5af 157 EveFTPDataAddMetadata(f, jb);
9cf4e2e4 158 } else {
648bd5af 159 EveFTPLogCommand(f, tx, jb);
9cf4e2e4
JL
160 }
161
03de315b
JL
162 if (!jb_close(jb)) {
163 goto fail;
9cf4e2e4 164 }
1930b1f5 165
06f58650 166 OutputJsonBuilderBuffer(jb, thread);
1930b1f5 167
03de315b 168 jb_free(jb);
1930b1f5
JL
169 }
170 return TM_ECODE_OK;
03de315b
JL
171
172fail:
173 jb_free(jb);
174 return TM_ECODE_FAILED;
1930b1f5
JL
175}
176
1930b1f5
JL
177static OutputInitResult OutputFTPLogInitSub(ConfNode *conf,
178 OutputCtx *parent_ctx)
179{
1930b1f5
JL
180 AppLayerParserRegisterLogger(IPPROTO_TCP, ALPROTO_FTP);
181 AppLayerParserRegisterLogger(IPPROTO_TCP, ALPROTO_FTPDATA);
67c4621b 182 return OutputJsonLogInitSub(conf, parent_ctx);
1930b1f5
JL
183}
184
185void JsonFTPLogRegister(void)
186{
187 /* Register as an eve sub-module. */
67c4621b
JI
188 OutputRegisterTxSubModule(LOGGER_JSON_FTP, "eve-log", "JsonFTPLog", "eve-log.ftp",
189 OutputFTPLogInitSub, ALPROTO_FTP, JsonFTPLogger, JsonLogThreadInit, JsonLogThreadDeinit,
190 NULL);
191 OutputRegisterTxSubModule(LOGGER_JSON_FTP, "eve-log", "JsonFTPLog", "eve-log.ftp",
192 OutputFTPLogInitSub, ALPROTO_FTPDATA, JsonFTPLogger, JsonLogThreadInit,
193 JsonLogThreadDeinit, NULL);
1930b1f5
JL
194
195 SCLogDebug("FTP JSON logger registered.");
196}