suricata
app-layer-tftp.c
Go to the documentation of this file.
1 /* Copyright (C) 2017-2024 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 "suricata.h"
30 
31 #include "app-layer.h"
32 #include "app-layer-detect-proto.h"
33 #include "app-layer-parser.h"
34 
35 #include "app-layer-tftp.h"
36 
37 /* The default port to probe if not provided in the configuration file. */
38 #define TFTP_DEFAULT_PORT "69"
39 
40 /* The minimum size for an message. For some protocols this might
41  * be the size of a header. */
42 #define TFTP_MIN_FRAME_LEN 4
43 
44 static void *TFTPStateAlloc(void *orig_state, AppProto proto_orig)
45 {
46  return rs_tftp_state_alloc();
47 }
48 
49 static void TFTPStateFree(void *state)
50 {
51  rs_tftp_state_free(state);
52 }
53 
54 /**
55  * \brief Callback from the application layer to have a transaction freed.
56  *
57  * \param state a void pointer to the TFTPState object.
58  * \param tx_id the transaction ID to free.
59  */
60 static void TFTPStateTxFree(void *state, uint64_t tx_id)
61 {
62  rs_tftp_state_tx_free(state, tx_id);
63 }
64 
65 static int TFTPStateGetEventInfo(
66  const char *event_name, uint8_t *event_id, AppLayerEventType *event_type)
67 {
68  return -1;
69 }
70 
71 /**
72  * \brief Probe the input to see if it looks like tftp.
73  *
74  * \retval ALPROTO_TFTP if it looks like tftp, otherwise
75  * ALPROTO_UNKNOWN.
76  */
77 static AppProto TFTPProbingParser(Flow *f, uint8_t direction,
78  const uint8_t *input, uint32_t input_len, uint8_t *rdir)
79 {
80  /* Very simple test - if there is input, this is tftp.
81  * Also check if it's starting by a zero */
82  if (input_len >= TFTP_MIN_FRAME_LEN && *input == 0) {
83  SCLogDebug("Detected as ALPROTO_TFTP.");
84  return ALPROTO_TFTP;
85  }
86 
87  SCLogDebug("Protocol not detected as ALPROTO_TFTP.");
88  return ALPROTO_UNKNOWN;
89 }
90 
91 static AppLayerResult TFTPParseRequest(Flow *f, void *state, AppLayerParserState *pstate,
92  StreamSlice stream_slice, void *local_data)
93 {
94  const uint8_t *input = StreamSliceGetData(&stream_slice);
95  uint32_t input_len = StreamSliceGetDataLen(&stream_slice);
96 
97  SCLogDebug("Parsing tftp request: len=%" PRIu32, input_len);
98 
99  /* Likely connection closed, we can just return here. */
100  if ((input == NULL || input_len == 0) &&
103  }
104 
105  /* Probably don't want to create a transaction in this case
106  * either. */
107  if (input == NULL || input_len == 0) {
109  }
110 
111  int64_t res = rs_tftp_request(state, input, input_len);
112  if (res < 0) {
114  }
116 }
117 
118 /**
119  * \brief Response parsing is not implemented
120  */
121 static AppLayerResult TFTPParseResponse(Flow *f, void *state, AppLayerParserState *pstate,
122  StreamSlice stream_slice, void *local_data)
123 {
125 }
126 
127 static uint64_t TFTPGetTxCnt(void *state)
128 {
129  return rs_tftp_get_tx_cnt(state);
130 }
131 
132 static void *TFTPGetTx(void *state, uint64_t tx_id)
133 {
134  return rs_tftp_get_tx(state, tx_id);
135 }
136 
137 /**
138  * \brief Return the state of a transaction in a given direction.
139  *
140  * In the case of the tftp protocol, the existence of a transaction
141  * means that the request is done. However, some protocols that may
142  * need multiple chunks of data to complete the request may need more
143  * than just the existence of a transaction for the request to be
144  * considered complete.
145  *
146  * For the response to be considered done, the response for a request
147  * needs to be seen. The response_done flag is set on response for
148  * checking here.
149  */
150 static int TFTPGetStateProgress(void *tx, uint8_t direction)
151 {
152  return 1;
153 }
154 
156 {
157  const char *proto_name = "tftp";
158 
159  /* Check if TFTP UDP detection is enabled. If it does not exist in
160  * the configuration file then it will be enabled by default. */
161  if (AppLayerProtoDetectConfProtoDetectionEnabled("udp", proto_name)) {
162 
163  SCLogDebug("TFTP UDP protocol detection enabled.");
164 
166 
167  if (RunmodeIsUnittests()) {
168  SCLogDebug("Unittest mode, registering default configuration.");
171  STREAM_TOSERVER, TFTPProbingParser,
172  TFTPProbingParser);
173  } else {
174  if (!AppLayerProtoDetectPPParseConfPorts("udp", IPPROTO_UDP,
175  proto_name, ALPROTO_TFTP,
177  TFTPProbingParser, TFTPProbingParser)) {
178  SCLogDebug("No tftp app-layer configuration, enabling tftp"
179  " detection UDP detection on port %s.",
181  AppLayerProtoDetectPPRegister(IPPROTO_UDP,
184  STREAM_TOSERVER,TFTPProbingParser,
185  TFTPProbingParser);
186  }
187  }
189  } else {
190  SCLogDebug("Protocol detector and parser disabled for TFTP.");
191  return;
192  }
193 
194  if (AppLayerParserConfParserEnabled("udp", proto_name)) {
195 
196  SCLogDebug("Registering TFTP protocol parser.");
197 
198  /* Register functions for state allocation and freeing. A
199  * state is allocated for every new TFTP flow. */
201  TFTPStateAlloc, TFTPStateFree);
202 
203  /* Register request parser for parsing frame from server to client. */
205  STREAM_TOSERVER, TFTPParseRequest);
206 
207  /* Register response parser for parsing frames from server to client. */
209  STREAM_TOCLIENT, TFTPParseResponse);
210 
211  /* Register a function to be called by the application layer
212  * when a transaction is to be freed. */
214  TFTPStateTxFree);
215 
216  /* Register a function to return the current transaction count. */
218  TFTPGetTxCnt);
219 
220  /* Transaction handling. */
223  ALPROTO_TFTP,
224  TFTPGetStateProgress);
226  TFTPGetTx);
227 
229  TFTPStateGetEventInfo);
230 
232  rs_tftp_get_tx_data);
233  AppLayerParserRegisterStateDataFunc(IPPROTO_UDP, ALPROTO_TFTP, rs_tftp_get_state_data);
234  }
235  else {
236  SCLogDebug("TFTP protocol parsing disabled.");
237  }
238 }
AppLayerParserRegisterGetStateProgressFunc
void AppLayerParserRegisterGetStateProgressFunc(uint8_t ipproto, AppProto alproto, int(*StateGetProgress)(void *alstate, uint8_t direction))
Definition: app-layer-parser.c:466
AppLayerProtoDetectPPParseConfPorts
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)
Definition: app-layer-detect-proto.c:1583
app-layer-tftp.h
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:269
AppProto
uint16_t AppProto
Definition: app-layer-protos.h:81
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:320
Flow_
Flow data structure.
Definition: flow.h:356
AppLayerParserRegisterStateProgressCompletionStatus
void AppLayerParserRegisterStateProgressCompletionStatus(AppProto alproto, const int ts, const int tc)
Definition: app-layer-parser.c:518
AppLayerParserRegisterTxFreeFunc
void AppLayerParserRegisterTxFreeFunc(uint8_t ipproto, AppProto alproto, void(*StateTransactionFree)(void *, uint64_t))
Definition: app-layer-parser.c:477
APP_LAYER_PARSER_EOF_TS
#define APP_LAYER_PARSER_EOF_TS
Definition: app-layer-parser.h:39
AppLayerProtoDetectPPRegister
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
Definition: app-layer-detect-proto.c:1543
app-layer-detect-proto.h
AppLayerParserState_
Definition: app-layer-parser.c:129
AppLayerParserRegisterLogger
void AppLayerParserRegisterLogger(uint8_t ipproto, AppProto alproto)
Definition: app-layer-parser.c:457
AppLayerParserRegisterStateFuncs
void AppLayerParserRegisterStateFuncs(uint8_t ipproto, AppProto alproto, void *(*StateAlloc)(void *, AppProto), void(*StateFree)(void *))
Definition: app-layer-parser.c:411
app-layer-parser.h
AppLayerParserRegisterGetEventInfo
void AppLayerParserRegisterGetEventInfo(uint8_t ipproto, AppProto alproto, int(*StateGetEventInfo)(const char *event_name, uint8_t *event_id, AppLayerEventType *event_type))
Definition: app-layer-parser.c:555
RegisterTFTPParsers
void RegisterTFTPParsers(void)
Definition: app-layer-tftp.c:155
TFTP_DEFAULT_PORT
#define TFTP_DEFAULT_PORT
Definition: app-layer-tftp.c:38
AppLayerProtoDetectRegisterProtocol
void AppLayerProtoDetectRegisterProtocol(AppProto alproto, const char *alproto_name)
Registers a protocol for protocol detection phase.
Definition: app-layer-detect-proto.c:1761
ALPROTO_TFTP
@ ALPROTO_TFTP
Definition: app-layer-protos.h:48
RunmodeIsUnittests
int RunmodeIsUnittests(void)
Definition: suricata.c:251
TFTP_MIN_FRAME_LEN
#define TFTP_MIN_FRAME_LEN
Definition: app-layer-tftp.c:42
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:378
AppLayerParserRegisterGetTx
void AppLayerParserRegisterGetTx(uint8_t ipproto, AppProto alproto, void *(StateGetTx)(void *alstate, uint64_t tx_id))
Definition: app-layer-parser.c:499
APP_LAYER_OK
#define APP_LAYER_OK
Definition: app-layer-parser.h:87
SCReturnStruct
#define SCReturnStruct(x)
Definition: util-debug.h:291
suricata-common.h
AppLayerParserRegisterStateDataFunc
void AppLayerParserRegisterStateDataFunc(uint8_t ipproto, AppProto alproto, AppLayerStateData *(*GetStateData)(void *state))
Definition: app-layer-parser.c:577
AppLayerParserRegisterTxDataFunc
void AppLayerParserRegisterTxDataFunc(uint8_t ipproto, AppProto alproto, AppLayerTxData *(*GetTxData)(void *tx))
Definition: app-layer-parser.c:567
ALPROTO_UNKNOWN
@ ALPROTO_UNKNOWN
Definition: app-layer-protos.h:29
suricata.h
AppLayerParserRegisterGetTxCnt
void AppLayerParserRegisterGetTxCnt(uint8_t ipproto, AppProto alproto, uint64_t(*StateGetTxCnt)(void *alstate))
Definition: app-layer-parser.c:488
APP_LAYER_ERROR
#define APP_LAYER_ERROR
Definition: app-layer-parser.h:91
AppLayerParserStateIssetFlag
uint16_t AppLayerParserStateIssetFlag(AppLayerParserState *pstate, uint16_t flag)
Definition: app-layer-parser.c:1760
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:1952
app-layer.h