]> git.ipfire.org Git - people/ms/suricata.git/blame - src/app-layer-tftp.c
detect: fix delayed detect
[people/ms/suricata.git] / src / app-layer-tftp.c
CommitLineData
b9cf49e9
CG
1/* Copyright (C) 2017 Open Information Security Foundation
2 *
3 * You can copy, redistribute or modify this Program under the terms of
4 * the GNU General Public License version 2 as published by the Free
5 * Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * version 2 along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 *
17 */
18
19/**
20 * \file
21 *
22 * \author Clément Galland <clement.galland@epita.fr>
23 *
24 * Parser for NTP application layer running on UDP port 69.
25 */
26
27
28#include "suricata-common.h"
29#include "stream.h"
30#include "conf.h"
31
32#include "util-unittest.h"
33
34#include "app-layer-detect-proto.h"
35#include "app-layer-parser.h"
36
37#include "app-layer-tftp.h"
38
39#ifndef HAVE_RUST
40
41void RegisterTFTPParsers(void)
42{
43}
44
45#else
46
47#include "rust-tftp-tftp-gen.h"
48
49/* The default port to probe if not provided in the configuration file. */
50#define TFTP_DEFAULT_PORT "69"
51
52/* The minimum size for an message. For some protocols this might
53 * be the size of a header. */
54#define TFTP_MIN_FRAME_LEN 4
55
56/* Enum of app-layer events for an echo protocol. Normally you might
57 * have events for errors in parsing data, like unexpected data being
58 * received. For echo we'll make something up, and log an app-layer
59 * level alert if an empty message is received.
60 *
61 * Example rule:
62 *
63 * alert tftp any any -> any any (msg:"SURICATA TFTP empty message"; \
64 * app-layer-event:tftp.empty_message; sid:X; rev:Y;)
65 */
66enum {
67 TFTP_DECODER_EVENT_EMPTY_MESSAGE,
68};
69
70SCEnumCharMap tftp_decoder_event_table[] = {
71 {"EMPTY_MESSAGE", TFTP_DECODER_EVENT_EMPTY_MESSAGE},
72
73 // event table must be NULL-terminated
74 { NULL, -1 },
75};
76
77static void *TFTPStateAlloc(void)
78{
79 return rs_tftp_state_alloc();
80}
81
82static void TFTPStateFree(void *state)
83{
84 rs_tftp_state_free(state);
85}
86
87/**
88 * \brief Callback from the application layer to have a transaction freed.
89 *
90 * \param state a void pointer to the TFTPState object.
91 * \param tx_id the transaction ID to free.
92 */
93static void TFTPStateTxFree(void *state, uint64_t tx_id)
94{
95 rs_tftp_state_tx_free(state, tx_id);
96}
97
98static int TFTPStateGetEventInfo(const char *event_name, int *event_id,
99 AppLayerEventType *event_type)
100{
101 return -1;
102}
103
104static AppLayerDecoderEvents *TFTPGetEvents(void *state, uint64_t tx_id)
105{
106 return NULL;
107}
108
b9cf49e9
CG
109/**
110 * \brief Probe the input to see if it looks like echo.
111 *
112 * \retval ALPROTO_TFTP if it looks like echo, otherwise
113 * ALPROTO_UNKNOWN.
114 */
115static AppProto TFTPProbingParser(Flow *f, uint8_t *input, uint32_t input_len,
116 uint32_t *offset)
117{
80f2fbac 118 /* Very simple test - if there is input, this is tftp.
b9cf49e9
CG
119 * Also check if it's starting by a zero */
120 if (input_len >= TFTP_MIN_FRAME_LEN && *input == 0) {
121 SCLogDebug("Detected as ALPROTO_TFTP.");
122 return ALPROTO_TFTP;
123 }
124
125 SCLogDebug("Protocol not detected as ALPROTO_TFTP.");
126 return ALPROTO_UNKNOWN;
127}
128
129static int TFTPParseRequest(Flow *f, void *state,
130 AppLayerParserState *pstate, uint8_t *input, uint32_t input_len,
131 void *local_data)
132{
133 SCLogDebug("Parsing echo request: len=%"PRIu32, input_len);
134
135 /* Likely connection closed, we can just return here. */
136 if ((input == NULL || input_len == 0) &&
137 AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF)) {
138 return 0;
139 }
140
141 /* Probably don't want to create a transaction in this case
142 * either. */
143 if (input == NULL || input_len == 0) {
144 return 0;
145 }
146
147 return rs_tftp_request(state, input, input_len);
148}
149
150/**
151 * \brief Response parsing is not implemented
152 */
153static int TFTPParseResponse(Flow *f, void *state, AppLayerParserState *pstate,
154 uint8_t *input, uint32_t input_len, void *local_data)
155{
156 return 0;
157}
158
159static uint64_t TFTPGetTxCnt(void *state)
160{
161 return rs_tftp_get_tx_cnt(state);
162}
163
164static void *TFTPGetTx(void *state, uint64_t tx_id)
165{
166 return rs_tftp_get_tx(state, tx_id);
167}
168
169static void TFTPSetTxLogged(void *state, void *vtx, uint32_t logger)
170{
171 rs_tftp_set_tx_logged(state, vtx, logger);
172}
173
80f2fbac 174static LoggerId TFTPGetTxLogged(void *state, void *vtx)
b9cf49e9 175{
80f2fbac 176 return rs_tftp_get_tx_logged(state, vtx);
b9cf49e9
CG
177}
178
179/**
180 * \brief Called by the application layer.
181 *
182 * In most cases 1 can be returned here.
183 */
184static int TFTPGetAlstateProgressCompletionStatus(uint8_t direction) {
185 return 1;
186}
187
188/**
189 * \brief Return the state of a transaction in a given direction.
190 *
191 * In the case of the echo protocol, the existence of a transaction
192 * means that the request is done. However, some protocols that may
193 * need multiple chunks of data to complete the request may need more
194 * than just the existence of a transaction for the request to be
195 * considered complete.
196 *
197 * For the response to be considered done, the response for a request
198 * needs to be seen. The response_done flag is set on response for
199 * checking here.
200 */
201static int TFTPGetStateProgress(void *tx, uint8_t direction)
202{
203 return 1;
204}
205
206static DetectEngineState *TFTPGetTxDetectState(void *vtx)
207{
208 return NULL;
209}
210
7548944b 211static int TFTPSetTxDetectState(void *vtx,
b9cf49e9
CG
212 DetectEngineState *s)
213{
214 return 0;
215}
216
217void RegisterTFTPParsers(void)
218{
219 const char *proto_name = "tftp";
220
221 /* Check if TFTP UDP detection is enabled. If it does not exist in
222 * the configuration file then it will be enabled by default. */
223 if (AppLayerProtoDetectConfProtoDetectionEnabled("udp", proto_name)) {
224
225 SCLogDebug("TFTP UDP protocol detection enabled.");
226
227 AppLayerProtoDetectRegisterProtocol(ALPROTO_TFTP, proto_name);
228
229 if (RunmodeIsUnittests()) {
230 SCLogDebug("Unittest mode, registeringd default configuration.");
231 AppLayerProtoDetectPPRegister(IPPROTO_UDP, TFTP_DEFAULT_PORT,
232 ALPROTO_TFTP, 0, TFTP_MIN_FRAME_LEN,
233 STREAM_TOSERVER, TFTPProbingParser,
234 NULL);
235 } else {
236 if (!AppLayerProtoDetectPPParseConfPorts("udp", IPPROTO_UDP,
237 proto_name, ALPROTO_TFTP,
238 0, TFTP_MIN_FRAME_LEN,
239 TFTPProbingParser, NULL)) {
240 SCLogDebug("No echo app-layer configuration, enabling echo"
241 " detection UDP detection on port %s.",
242 TFTP_DEFAULT_PORT);
243 AppLayerProtoDetectPPRegister(IPPROTO_UDP,
244 TFTP_DEFAULT_PORT, ALPROTO_TFTP,
245 0, TFTP_MIN_FRAME_LEN,
246 STREAM_TOSERVER,TFTPProbingParser,
247 NULL);
248 }
249 }
250 } else {
251 SCLogDebug("Protocol detecter and parser disabled for TFTP.");
252 return;
253 }
254
255 if (AppLayerParserConfParserEnabled("udp", proto_name)) {
256
257 SCLogDebug("Registering TFTP protocol parser.");
258
259 /* Register functions for state allocation and freeing. A
260 * state is allocated for every new TFTP flow. */
261 AppLayerParserRegisterStateFuncs(IPPROTO_UDP, ALPROTO_TFTP,
262 TFTPStateAlloc, TFTPStateFree);
263
264 /* Register request parser for parsing frame from server to client. */
265 AppLayerParserRegisterParser(IPPROTO_UDP, ALPROTO_TFTP,
266 STREAM_TOSERVER, TFTPParseRequest);
267
268 /* Register response parser for parsing frames from server to client. */
269 AppLayerParserRegisterParser(IPPROTO_UDP, ALPROTO_TFTP,
270 STREAM_TOCLIENT, TFTPParseResponse);
271
272 /* Register a function to be called by the application layer
273 * when a transaction is to be freed. */
274 AppLayerParserRegisterTxFreeFunc(IPPROTO_UDP, ALPROTO_TFTP,
275 TFTPStateTxFree);
276
277 AppLayerParserRegisterLoggerFuncs(IPPROTO_UDP, ALPROTO_TFTP,
278 TFTPGetTxLogged, TFTPSetTxLogged);
279
280 /* Register a function to return the current transaction count. */
281 AppLayerParserRegisterGetTxCnt(IPPROTO_UDP, ALPROTO_TFTP,
282 TFTPGetTxCnt);
283
284 /* Transaction handling. */
285 AppLayerParserRegisterGetStateProgressCompletionStatus(ALPROTO_TFTP,
286 TFTPGetAlstateProgressCompletionStatus);
287 AppLayerParserRegisterGetStateProgressFunc(IPPROTO_UDP,
288 ALPROTO_TFTP,
289 TFTPGetStateProgress);
290 AppLayerParserRegisterGetTx(IPPROTO_UDP, ALPROTO_TFTP,
291 TFTPGetTx);
292
b9cf49e9
CG
293 /* What is this being registered for? */
294 AppLayerParserRegisterDetectStateFuncs(IPPROTO_UDP, ALPROTO_TFTP,
7548944b 295 TFTPGetTxDetectState,
b9cf49e9
CG
296 TFTPSetTxDetectState);
297
298 AppLayerParserRegisterGetEventInfo(IPPROTO_UDP, ALPROTO_TFTP,
299 TFTPStateGetEventInfo);
300 AppLayerParserRegisterGetEventsFunc(IPPROTO_UDP, ALPROTO_TFTP,
301 TFTPGetEvents);
302 }
303 else {
304 SCLogDebug("TFTP protocol parsing disabled.");
305 }
306
307#ifdef UNITTESTS
308 AppLayerParserRegisterProtocolUnittests(IPPROTO_UDP, ALPROTO_TFTP,
309 TFTPParserRegisterTests);
310#endif
311}
312
313#ifdef UNITTESTS
314#endif
315
316void TFTPParserRegisterTests(void)
317{
318#ifdef UNITTESTS
319#endif
320}
321
322#endif /* HAVE_RUST */