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"
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
44static void *TFTPStateAlloc(void *orig_state, AppProto proto_orig)
45{
46 return SCTftpStateAlloc();
47}
48
49static void TFTPStateFree(void *state)
50{
51 SCTftpStateFree(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 */
60static void TFTPStateTxFree(void *state, uint64_t tx_id)
61{
62 SCTftpStateTxFree(state, tx_id);
63}
64
65static 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 */
77static AppProto TFTPProbingParser(
78 const Flow *f, uint8_t direction, 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
91static 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 = SCTftpParseRequest(state, input, input_len);
112 if (res < 0) {
114 }
116}
117
118/**
119 * \brief Response parsing is not implemented
120 */
121static AppLayerResult TFTPParseResponse(Flow *f, void *state, AppLayerParserState *pstate,
122 StreamSlice stream_slice, void *local_data)
123{
125}
126
127static uint64_t TFTPGetTxCnt(void *state)
128{
129 return SCTftpGetTxCnt(state);
130}
131
132static void *TFTPGetTx(void *state, uint64_t tx_id)
133{
134 return SCTftpGetTx(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 */
150static 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 (SCAppLayerProtoDetectConfProtoDetectionEnabled("udp", proto_name)) {
162
163 SCLogDebug("TFTP UDP protocol detection enabled.");
164
166
167 if (RunmodeIsUnittests()) {
168 SCLogDebug("Unittest mode, registering default configuration.");
170 TFTP_MIN_FRAME_LEN, STREAM_TOSERVER, TFTPProbingParser, TFTPProbingParser);
171 } else {
172 if (!SCAppLayerProtoDetectPPParseConfPorts("udp", IPPROTO_UDP, proto_name, ALPROTO_TFTP,
173 0, TFTP_MIN_FRAME_LEN, TFTPProbingParser, TFTPProbingParser)) {
174 SCLogDebug("No tftp app-layer configuration, enabling tftp"
175 " detection UDP detection on port %s.",
178 TFTP_MIN_FRAME_LEN, STREAM_TOSERVER, TFTPProbingParser, TFTPProbingParser);
179 }
180 }
182 } else {
183 SCLogDebug("Protocol detector and parser disabled for TFTP.");
184 return;
185 }
186
187 if (SCAppLayerParserConfParserEnabled("udp", proto_name)) {
188
189 SCLogDebug("Registering TFTP protocol parser.");
190
191 /* Register functions for state allocation and freeing. A
192 * state is allocated for every new TFTP flow. */
194 TFTPStateAlloc, TFTPStateFree);
195
196 /* Register request parser for parsing frame from server to client. */
198 STREAM_TOSERVER, TFTPParseRequest);
199
200 /* Register response parser for parsing frames from server to client. */
202 STREAM_TOCLIENT, TFTPParseResponse);
203
204 /* Register a function to be called by the application layer
205 * when a transaction is to be freed. */
207 TFTPStateTxFree);
208
209 /* Register a function to return the current transaction count. */
211 TFTPGetTxCnt);
212
213 /* Transaction handling. */
217 TFTPGetStateProgress);
219 TFTPGetTx);
220
222 TFTPStateGetEventInfo);
223
224 AppLayerParserRegisterTxDataFunc(IPPROTO_UDP, ALPROTO_TFTP, SCTftpGetTxData);
225 AppLayerParserRegisterStateDataFunc(IPPROTO_UDP, ALPROTO_TFTP, SCTftpGetStateData);
226 } else {
227 SCLogDebug("TFTP protocol parsing disabled.");
228 }
229}
void AppLayerProtoDetectRegisterProtocol(AppProto alproto, const char *alproto_name)
Registers a protocol for protocol detection phase.
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)
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
int SCAppLayerProtoDetectConfProtoDetectionEnabled(const char *ipproto, const char *alproto)
Given a protocol name, checks if proto detection is enabled in the conf file.
void AppLayerParserRegisterGetTxCnt(uint8_t ipproto, AppProto alproto, uint64_t(*StateGetTxCnt)(void *alstate))
void AppLayerParserRegisterTxFreeFunc(uint8_t ipproto, AppProto alproto, void(*StateTransactionFree)(void *, uint64_t))
uint16_t SCAppLayerParserStateIssetFlag(AppLayerParserState *pstate, uint16_t flag)
void AppLayerParserRegisterTxDataFunc(uint8_t ipproto, AppProto alproto, AppLayerTxData *(*GetTxData)(void *tx))
void AppLayerParserRegisterStateProgressCompletionStatus(AppProto alproto, const int ts, const int tc)
void AppLayerParserRegisterStateDataFunc(uint8_t ipproto, AppProto alproto, AppLayerStateData *(*GetStateData)(void *state))
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))
void SCAppLayerParserRegisterLogger(uint8_t ipproto, AppProto alproto)
void AppLayerParserRegisterGetEventInfo(uint8_t ipproto, AppProto alproto, int(*StateGetEventInfo)(const char *event_name, uint8_t *event_id, AppLayerEventType *event_type))
void AppLayerParserRegisterGetStateProgressFunc(uint8_t ipproto, AppProto alproto, int(*StateGetProgress)(void *alstate, uint8_t direction))
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
void AppLayerParserRegisterStateFuncs(uint8_t ipproto, AppProto alproto, void *(*StateAlloc)(void *, AppProto), void(*StateFree)(void *))
#define APP_LAYER_OK
struct AppLayerResult AppLayerResult
#define APP_LAYER_PARSER_EOF_TS
#define APP_LAYER_ERROR
struct StreamSlice StreamSlice
enum AppLayerEventType AppLayerEventType
uint16_t AppProto
@ ALPROTO_UNKNOWN
@ ALPROTO_TFTP
#define TFTP_MIN_FRAME_LEN
void RegisterTFTPParsers(void)
#define TFTP_DEFAULT_PORT
Flow data structure.
Definition flow.h:356
int RunmodeIsUnittests(void)
Definition suricata.c:270
#define SCLogDebug(...)
Definition util-debug.h:275
#define SCReturnStruct(x)
Definition util-debug.h:297