suricata
app-layer-tftp.c
Go to the documentation of this file.
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 
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  */
66 enum {
67  TFTP_DECODER_EVENT_EMPTY_MESSAGE,
68 };
69 
70 SCEnumCharMap 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 
77 static void *TFTPStateAlloc(void)
78 {
79  return rs_tftp_state_alloc();
80 }
81 
82 static 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  */
93 static void TFTPStateTxFree(void *state, uint64_t tx_id)
94 {
95  rs_tftp_state_tx_free(state, tx_id);
96 }
97 
98 static int TFTPStateGetEventInfo(const char *event_name, int *event_id,
100 {
101  return -1;
102 }
103 
104 static AppLayerDecoderEvents *TFTPGetEvents(void *state, uint64_t tx_id)
105 {
106  return NULL;
107 }
108 
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  */
115 static AppProto TFTPProbingParser(Flow *f, uint8_t direction,
116  uint8_t *input, uint32_t input_len, uint8_t *rdir)
117 {
118  /* Very simple test - if there is input, this is tftp.
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 
129 static int TFTPParseRequest(Flow *f, void *state,
130  AppLayerParserState *pstate, uint8_t *input, uint32_t input_len,
131  void *local_data, const uint8_t flags)
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) &&
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  */
153 static int TFTPParseResponse(Flow *f, void *state, AppLayerParserState *pstate,
154  uint8_t *input, uint32_t input_len, void *local_data,
155  const uint8_t flags)
156 {
157  return 0;
158 }
159 
160 static uint64_t TFTPGetTxCnt(void *state)
161 {
162  return rs_tftp_get_tx_cnt(state);
163 }
164 
165 static void *TFTPGetTx(void *state, uint64_t tx_id)
166 {
167  return rs_tftp_get_tx(state, tx_id);
168 }
169 
170 static void TFTPSetTxLogged(void *state, void *vtx, uint32_t logger)
171 {
172  rs_tftp_set_tx_logged(state, vtx, logger);
173 }
174 
175 static LoggerId TFTPGetTxLogged(void *state, void *vtx)
176 {
177  return rs_tftp_get_tx_logged(state, vtx);
178 }
179 
180 /**
181  * \brief Called by the application layer.
182  *
183  * In most cases 1 can be returned here.
184  */
185 static int TFTPGetAlstateProgressCompletionStatus(uint8_t direction) {
186  return 1;
187 }
188 
189 /**
190  * \brief Return the state of a transaction in a given direction.
191  *
192  * In the case of the echo protocol, the existence of a transaction
193  * means that the request is done. However, some protocols that may
194  * need multiple chunks of data to complete the request may need more
195  * than just the existence of a transaction for the request to be
196  * considered complete.
197  *
198  * For the response to be considered done, the response for a request
199  * needs to be seen. The response_done flag is set on response for
200  * checking here.
201  */
202 static int TFTPGetStateProgress(void *tx, uint8_t direction)
203 {
204  return 1;
205 }
206 
207 static DetectEngineState *TFTPGetTxDetectState(void *vtx)
208 {
209  return NULL;
210 }
211 
212 static int TFTPSetTxDetectState(void *vtx,
214 {
215  return 0;
216 }
217 
218 void RegisterTFTPParsers(void)
219 {
220  const char *proto_name = "tftp";
221 
222  /* Check if TFTP UDP detection is enabled. If it does not exist in
223  * the configuration file then it will be enabled by default. */
224  if (AppLayerProtoDetectConfProtoDetectionEnabled("udp", proto_name)) {
225 
226  SCLogDebug("TFTP UDP protocol detection enabled.");
227 
229 
230  if (RunmodeIsUnittests()) {
231  SCLogDebug("Unittest mode, registeringd default configuration.");
232  AppLayerProtoDetectPPRegister(IPPROTO_UDP, TFTP_DEFAULT_PORT,
233  ALPROTO_TFTP, 0, TFTP_MIN_FRAME_LEN,
234  STREAM_TOSERVER, TFTPProbingParser,
235  NULL);
236  } else {
237  if (!AppLayerProtoDetectPPParseConfPorts("udp", IPPROTO_UDP,
238  proto_name, ALPROTO_TFTP,
239  0, TFTP_MIN_FRAME_LEN,
240  TFTPProbingParser, NULL)) {
241  SCLogDebug("No echo app-layer configuration, enabling echo"
242  " detection UDP detection on port %s.",
243  TFTP_DEFAULT_PORT);
244  AppLayerProtoDetectPPRegister(IPPROTO_UDP,
245  TFTP_DEFAULT_PORT, ALPROTO_TFTP,
246  0, TFTP_MIN_FRAME_LEN,
247  STREAM_TOSERVER,TFTPProbingParser,
248  NULL);
249  }
250  }
251  } else {
252  SCLogDebug("Protocol detecter and parser disabled for TFTP.");
253  return;
254  }
255 
256  if (AppLayerParserConfParserEnabled("udp", proto_name)) {
257 
258  SCLogDebug("Registering TFTP protocol parser.");
259 
260  /* Register functions for state allocation and freeing. A
261  * state is allocated for every new TFTP flow. */
263  TFTPStateAlloc, TFTPStateFree);
264 
265  /* Register request parser for parsing frame from server to client. */
267  STREAM_TOSERVER, TFTPParseRequest);
268 
269  /* Register response parser for parsing frames from server to client. */
271  STREAM_TOCLIENT, TFTPParseResponse);
272 
273  /* Register a function to be called by the application layer
274  * when a transaction is to be freed. */
276  TFTPStateTxFree);
277 
279  TFTPGetTxLogged, TFTPSetTxLogged);
280 
281  /* Register a function to return the current transaction count. */
283  TFTPGetTxCnt);
284 
285  /* Transaction handling. */
287  TFTPGetAlstateProgressCompletionStatus);
289  ALPROTO_TFTP,
290  TFTPGetStateProgress);
292  TFTPGetTx);
293 
294  /* What is this being registered for? */
296  TFTPGetTxDetectState,
297  TFTPSetTxDetectState);
298 
300  TFTPStateGetEventInfo);
302  TFTPGetEvents);
303  }
304  else {
305  SCLogDebug("TFTP protocol parsing disabled.");
306  }
307 
308 #ifdef UNITTESTS
311 #endif
312 }
313 
314 #ifdef UNITTESTS
315 #endif
316 
317 void TFTPParserRegisterTests(void)
318 {
319 #ifdef UNITTESTS
320 #endif
321 }
322 
323 #endif /* HAVE_RUST */
void RegisterTFTPParsers(void)
enum AppLayerEventType_ AppLayerEventType
uint16_t flags
#define SCLogDebug(...)
Definition: util-debug.h:335
void AppLayerProtoDetectPPRegister(uint8_t ipproto, const char *portstr, AppProto alproto, uint16_t min_depth, uint16_t max_depth, uint8_t direction, ProbingParserFPtr ProbingParser1, ProbingParserFPtr ProbingParser2)
register parser at a port
void AppLayerParserRegisterGetStateProgressFunc(uint8_t ipproto, AppProto alproto, int(*StateGetProgress)(void *alstate, uint8_t direction))
uint32_t event_type
LoggerId
int AppLayerProtoDetectConfProtoDetectionEnabled(const char *ipproto, const char *alproto)
Given a protocol name, checks if proto detection is enabled in the conf file.
int AppLayerParserStateIssetFlag(AppLayerParserState *pstate, uint8_t flag)
void AppLayerParserRegisterDetectStateFuncs(uint8_t ipproto, AppProto alproto, DetectEngineState *(*GetTxDetectState)(void *tx), int(*SetTxDetectState)(void *tx, DetectEngineState *))
void AppLayerParserRegisterLoggerFuncs(uint8_t ipproto, AppProto alproto, LoggerId(*StateGetTxLogged)(void *, void *), void(*StateSetTxLogged)(void *, void *, LoggerId))
uint16_t AppProto
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 and when...
Data structure to store app layer decoder events.
int AppLayerParserRegisterParser(uint8_t ipproto, AppProto alproto, uint8_t direction, AppLayerParserFPtr Parser)
Register app layer parser for the protocol.
void AppLayerParserRegisterGetTx(uint8_t ipproto, AppProto alproto, void *(StateGetTx)(void *alstate, uint64_t tx_id))
int AppLayerProtoDetectPPParseConfPorts(const char *ipproto_name, uint8_t ipproto, const char *alproto_name, AppProto alproto, uint16_t min_depth, uint16_t max_depth, ProbingParserFPtr ProbingParserTs, ProbingParserFPtr ProbingParserTc)
void AppLayerParserRegisterGetEventInfo(uint8_t ipproto, AppProto alproto, int(*StateGetEventInfo)(const char *event_name, int *event_id, AppLayerEventType *event_type))
#define STREAM_TOCLIENT
Definition: stream.h:32
void AppLayerParserRegisterGetStateProgressCompletionStatus(AppProto alproto, int(*StateGetProgressCompletionStatus)(uint8_t direction))
int RunmodeIsUnittests(void)
Definition: suricata.c:259
void AppLayerProtoDetectRegisterProtocol(AppProto alproto, const char *alproto_name)
Registers a protocol for protocol detection phase.
uint16_t tx_id
void AppLayerParserRegisterGetEventsFunc(uint8_t ipproto, AppProto alproto, AppLayerDecoderEvents *(*StateGetEvents)(void *, uint64_t))
void AppLayerParserRegisterProtocolUnittests(uint8_t ipproto, AppProto alproto, void(*RegisterUnittests)(void))
void TFTPParserRegisterTests(void)
#define STREAM_TOSERVER
Definition: stream.h:31
#define APP_LAYER_PARSER_EOF
void AppLayerParserRegisterGetTxCnt(uint8_t ipproto, AppProto alproto, uint64_t(*StateGetTxCnt)(void *alstate))
void AppLayerParserRegisterStateFuncs(uint8_t ipproto, AppProto alproto, void *(*StateAlloc)(void), void(*StateFree)(void *))
Flow data structure.
Definition: flow.h:324
void AppLayerParserRegisterTxFreeFunc(uint8_t ipproto, AppProto alproto, void(*StateTransactionFree)(void *, uint64_t))