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-detect-proto.h"
32 #include "app-layer-parser.h"
33 
34 #include "app-layer-tftp.h"
35 #include "app-layer-protos.h"
36 #include "rust.h"
37 #include "util-debug.h"
38 
39 /* The default port to probe if not provided in the configuration file. */
40 #define TFTP_DEFAULT_PORT "69"
41 
42 /* The minimum size for an message. For some protocols this might
43  * be the size of a header. */
44 #define TFTP_MIN_FRAME_LEN 4
45 
46 static void *TFTPStateAlloc(void *orig_state, AppProto proto_orig)
47 {
48  return SCTftpStateAlloc();
49 }
50 
51 static void TFTPStateFree(void *state)
52 {
53  SCTftpStateFree(state);
54 }
55 
56 /**
57  * \brief Callback from the application layer to have a transaction freed.
58  *
59  * \param state a void pointer to the TFTPState object.
60  * \param tx_id the transaction ID to free.
61  */
62 static void TFTPStateTxFree(void *state, uint64_t tx_id)
63 {
64  SCTftpStateTxFree(state, tx_id);
65 }
66 
67 static int TFTPStateGetEventInfo(
68  const char *event_name, uint8_t *event_id, AppLayerEventType *event_type)
69 {
70  return -1;
71 }
72 
73 /**
74  * \brief Probe the input to see if it looks like tftp.
75  *
76  * \retval ALPROTO_TFTP if it looks like tftp, otherwise
77  * ALPROTO_UNKNOWN.
78  */
79 static AppProto TFTPProbingParser(
80  const Flow *f, uint8_t direction, const uint8_t *input, uint32_t input_len, uint8_t *rdir)
81 {
82  /* Very simple test - if there is input, this is tftp.
83  * Also check if it's starting by a zero */
84  if (input_len >= TFTP_MIN_FRAME_LEN && *input == 0) {
85  SCLogDebug("Detected as ALPROTO_TFTP.");
86  return ALPROTO_TFTP;
87  }
88 
89  SCLogDebug("Protocol not detected as ALPROTO_TFTP.");
90  return ALPROTO_UNKNOWN;
91 }
92 
93 static AppLayerResult TFTPParseRequest(Flow *f, void *state, AppLayerParserState *pstate,
94  StreamSlice stream_slice, void *local_data)
95 {
96  const uint8_t *input = StreamSliceGetData(&stream_slice);
97  uint32_t input_len = StreamSliceGetDataLen(&stream_slice);
98 
99  SCLogDebug("Parsing tftp request: len=%" PRIu32, input_len);
100 
101  /* Likely connection closed, we can just return here. */
102  if ((input == NULL || input_len == 0) &&
103  SCAppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF_TS)) {
105  }
106 
107  /* Probably don't want to create a transaction in this case
108  * either. */
109  if (input == NULL || input_len == 0) {
111  }
112 
113  int64_t res = SCTftpParseRequest(state, input, input_len);
114  if (res < 0) {
116  }
118 }
119 
120 /**
121  * \brief Response parsing is not implemented
122  */
123 static AppLayerResult TFTPParseResponse(Flow *f, void *state, AppLayerParserState *pstate,
124  StreamSlice stream_slice, void *local_data)
125 {
127 }
128 
129 static uint64_t TFTPGetTxCnt(void *state)
130 {
131  return SCTftpGetTxCnt(state);
132 }
133 
134 static void *TFTPGetTx(void *state, uint64_t tx_id)
135 {
136  return SCTftpGetTx(state, tx_id);
137 }
138 
139 /**
140  * \brief Return the state of a transaction in a given direction.
141  *
142  * In the case of the tftp protocol, the existence of a transaction
143  * means that the request is done. However, some protocols that may
144  * need multiple chunks of data to complete the request may need more
145  * than just the existence of a transaction for the request to be
146  * considered complete.
147  *
148  * For the response to be considered done, the response for a request
149  * needs to be seen. The response_done flag is set on response for
150  * checking here.
151  */
152 static int TFTPGetStateProgress(void *tx, uint8_t direction)
153 {
154  return 1;
155 }
156 
158 {
159  const char *proto_name = "tftp";
160 
161  /* Check if TFTP UDP detection is enabled. If it does not exist in
162  * the configuration file then it will be enabled by default. */
163  if (SCAppLayerProtoDetectConfProtoDetectionEnabled("udp", proto_name)) {
164 
165  SCLogDebug("TFTP UDP protocol detection enabled.");
166 
168 
169  if (RunmodeIsUnittests()) {
170  SCLogDebug("Unittest mode, registering default configuration.");
172  TFTP_MIN_FRAME_LEN, STREAM_TOSERVER, TFTPProbingParser, TFTPProbingParser);
173  } else {
174  if (!SCAppLayerProtoDetectPPParseConfPorts("udp", IPPROTO_UDP, proto_name, ALPROTO_TFTP,
175  0, TFTP_MIN_FRAME_LEN, TFTPProbingParser, TFTPProbingParser)) {
176  SCLogDebug("No tftp app-layer configuration, enabling tftp"
177  " detection UDP detection on port %s.",
180  TFTP_MIN_FRAME_LEN, STREAM_TOSERVER, TFTPProbingParser, TFTPProbingParser);
181  }
182  }
184  } else {
185  SCLogDebug("Protocol detector and parser disabled for TFTP.");
186  return;
187  }
188 
189  if (SCAppLayerParserConfParserEnabled("udp", proto_name)) {
190 
191  SCLogDebug("Registering TFTP protocol parser.");
192 
193  /* Register functions for state allocation and freeing. A
194  * state is allocated for every new TFTP flow. */
196  TFTPStateAlloc, TFTPStateFree);
197 
198  /* Register request parser for parsing frame from server to client. */
200  STREAM_TOSERVER, TFTPParseRequest);
201 
202  /* Register response parser for parsing frames from server to client. */
204  STREAM_TOCLIENT, TFTPParseResponse);
205 
206  /* Register a function to be called by the application layer
207  * when a transaction is to be freed. */
209  TFTPStateTxFree);
210 
211  /* Register a function to return the current transaction count. */
213  TFTPGetTxCnt);
214 
215  /* Transaction handling. */
218  ALPROTO_TFTP,
219  TFTPGetStateProgress);
221  TFTPGetTx);
222 
224  TFTPStateGetEventInfo);
225 
226  AppLayerParserRegisterTxDataFunc(IPPROTO_UDP, ALPROTO_TFTP, SCTftpGetTxData);
227  AppLayerParserRegisterStateDataFunc(IPPROTO_UDP, ALPROTO_TFTP, SCTftpGetStateData);
228  } else {
229  SCLogDebug("TFTP protocol parsing disabled.");
230  }
231 }
StreamSlice
Definition: app-layer-parser.h:126
AppLayerParserRegisterGetStateProgressFunc
void AppLayerParserRegisterGetStateProgressFunc(uint8_t ipproto, AppProto alproto, int(*StateGetProgress)(void *alstate, uint8_t direction))
Definition: app-layer-parser.c:544
SCAppLayerParserStateIssetFlag
uint16_t SCAppLayerParserStateIssetFlag(AppLayerParserState *pstate, uint16_t flag)
Definition: app-layer-parser.c:2079
app-layer-tftp.h
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:282
AppProto
uint16_t AppProto
Definition: app-layer-protos.h:87
Flow_
Flow data structure.
Definition: flow.h:360
AppLayerParserRegisterStateProgressCompletionStatus
void AppLayerParserRegisterStateProgressCompletionStatus(AppProto alproto, const int ts, const int tc)
Definition: app-layer-parser.c:592
AppLayerParserRegisterTxFreeFunc
void AppLayerParserRegisterTxFreeFunc(uint8_t ipproto, AppProto alproto, void(*StateTransactionFree)(void *, uint64_t))
Definition: app-layer-parser.c:554
rust.h
SCAppLayerProtoDetectConfProtoDetectionEnabled
int SCAppLayerProtoDetectConfProtoDetectionEnabled(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:1989
AppLayerResult
Definition: app-layer-parser.h:120
app-layer-detect-proto.h
util-debug.h
AppLayerParserState_
Definition: app-layer-parser.c:160
SCAppLayerParserConfParserEnabled
int SCAppLayerParserConfParserEnabled(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:385
SCAppLayerParserRegisterLogger
void SCAppLayerParserRegisterLogger(uint8_t ipproto, AppProto alproto)
Definition: app-layer-parser.c:535
AppLayerEventType
AppLayerEventType
Definition: app-layer-events.h:54
AppLayerParserRegisterStateFuncs
void AppLayerParserRegisterStateFuncs(uint8_t ipproto, AppProto alproto, void *(*StateAlloc)(void *, AppProto), void(*StateFree)(void *))
Definition: app-layer-parser.c:493
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:671
RegisterTFTPParsers
void RegisterTFTPParsers(void)
Definition: app-layer-tftp.c:157
TFTP_DEFAULT_PORT
#define TFTP_DEFAULT_PORT
Definition: app-layer-tftp.c:40
AppLayerProtoDetectRegisterProtocol
void AppLayerProtoDetectRegisterProtocol(AppProto alproto, const char *alproto_name)
Registers a protocol for protocol detection phase.
Definition: app-layer-detect-proto.c:1769
ALPROTO_TFTP
@ ALPROTO_TFTP
Definition: app-layer-protos.h:54
RunmodeIsUnittests
int RunmodeIsUnittests(void)
Definition: suricata.c:292
TFTP_MIN_FRAME_LEN
#define TFTP_MIN_FRAME_LEN
Definition: app-layer-tftp.c:44
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:460
SCAppLayerProtoDetectPPRegister
void SCAppLayerProtoDetectPPRegister(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:1528
AppLayerParserRegisterGetTx
void AppLayerParserRegisterGetTx(uint8_t ipproto, AppProto alproto, void *(StateGetTx)(void *alstate, uint64_t tx_id))
Definition: app-layer-parser.c:574
APP_LAYER_OK
#define APP_LAYER_OK
Definition: app-layer-parser.h:58
SCReturnStruct
#define SCReturnStruct(x)
Definition: util-debug.h:304
suricata-common.h
AppLayerParserRegisterStateDataFunc
void AppLayerParserRegisterStateDataFunc(uint8_t ipproto, AppProto alproto, AppLayerStateData *(*GetStateData)(void *state))
Definition: app-layer-parser.c:692
AppLayerParserRegisterTxDataFunc
void AppLayerParserRegisterTxDataFunc(uint8_t ipproto, AppProto alproto, AppLayerTxData *(*GetTxData)(void *tx))
Definition: app-layer-parser.c:682
SCAppLayerProtoDetectPPParseConfPorts
int SCAppLayerProtoDetectPPParseConfPorts(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:1564
ALPROTO_UNKNOWN
@ ALPROTO_UNKNOWN
Definition: app-layer-protos.h:29
app-layer-protos.h
suricata.h
AppLayerParserRegisterGetTxCnt
void AppLayerParserRegisterGetTxCnt(uint8_t ipproto, AppProto alproto, uint64_t(*StateGetTxCnt)(void *alstate))
Definition: app-layer-parser.c:564
APP_LAYER_ERROR
#define APP_LAYER_ERROR
Definition: app-layer-parser.h:62
f
Flow f
Definition: fuzz_dataset.c:32