]> git.ipfire.org Git - people/ms/suricata.git/blame - src/app-layer-tftp.c
app-layer: include decoder events in app-layer tx data
[people/ms/suricata.git] / src / app-layer-tftp.c
CommitLineData
e0debed0 1/* Copyright (C) 2017-2020 Open Information Security Foundation
b9cf49e9
CG
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"
b573c16d 38#include "rust.h"
b9cf49e9
CG
39
40/* The default port to probe if not provided in the configuration file. */
41#define TFTP_DEFAULT_PORT "69"
42
43/* The minimum size for an message. For some protocols this might
44 * be the size of a header. */
45#define TFTP_MIN_FRAME_LEN 4
46
547d6c2d 47static void *TFTPStateAlloc(void *orig_state, AppProto proto_orig)
b9cf49e9
CG
48{
49 return rs_tftp_state_alloc();
50}
51
52static void TFTPStateFree(void *state)
53{
54 rs_tftp_state_free(state);
55}
56
57/**
58 * \brief Callback from the application layer to have a transaction freed.
59 *
60 * \param state a void pointer to the TFTPState object.
61 * \param tx_id the transaction ID to free.
62 */
63static void TFTPStateTxFree(void *state, uint64_t tx_id)
64{
65 rs_tftp_state_tx_free(state, tx_id);
66}
67
68static int TFTPStateGetEventInfo(const char *event_name, int *event_id,
69 AppLayerEventType *event_type)
70{
71 return -1;
72}
73
b9cf49e9 74/**
6a470a84 75 * \brief Probe the input to see if it looks like tftp.
b9cf49e9 76 *
6a470a84 77 * \retval ALPROTO_TFTP if it looks like tftp, otherwise
b9cf49e9
CG
78 * ALPROTO_UNKNOWN.
79 */
422e4892 80static AppProto TFTPProbingParser(Flow *f, uint8_t direction,
579cc9f0 81 const uint8_t *input, uint32_t input_len, uint8_t *rdir)
b9cf49e9 82{
80f2fbac 83 /* Very simple test - if there is input, this is tftp.
b9cf49e9
CG
84 * Also check if it's starting by a zero */
85 if (input_len >= TFTP_MIN_FRAME_LEN && *input == 0) {
86 SCLogDebug("Detected as ALPROTO_TFTP.");
87 return ALPROTO_TFTP;
88 }
89
90 SCLogDebug("Protocol not detected as ALPROTO_TFTP.");
91 return ALPROTO_UNKNOWN;
92}
93
44d3f264 94static AppLayerResult TFTPParseRequest(Flow *f, void *state,
579cc9f0 95 AppLayerParserState *pstate, const uint8_t *input, uint32_t input_len,
7bc3c3ac 96 void *local_data, const uint8_t flags)
b9cf49e9 97{
6a470a84 98 SCLogDebug("Parsing tftp request: len=%" PRIu32, input_len);
b9cf49e9
CG
99
100 /* Likely connection closed, we can just return here. */
101 if ((input == NULL || input_len == 0) &&
4f73943d 102 AppLayerParserStateIssetFlag(pstate, APP_LAYER_PARSER_EOF_TS)) {
44d3f264 103 SCReturnStruct(APP_LAYER_OK);
b9cf49e9
CG
104 }
105
106 /* Probably don't want to create a transaction in this case
107 * either. */
108 if (input == NULL || input_len == 0) {
44d3f264 109 SCReturnStruct(APP_LAYER_OK);
b9cf49e9
CG
110 }
111
44d3f264
VJ
112 int res = rs_tftp_request(state, input, input_len);
113 if (res < 0) {
114 SCReturnStruct(APP_LAYER_ERROR);
115 }
116 SCReturnStruct(APP_LAYER_OK);
b9cf49e9
CG
117}
118
119/**
120 * \brief Response parsing is not implemented
121 */
44d3f264 122static AppLayerResult TFTPParseResponse(Flow *f, void *state, AppLayerParserState *pstate,
579cc9f0 123 const uint8_t *input, uint32_t input_len, void *local_data,
7bc3c3ac 124 const uint8_t flags)
b9cf49e9 125{
44d3f264 126 SCReturnStruct(APP_LAYER_OK);
b9cf49e9
CG
127}
128
129static uint64_t TFTPGetTxCnt(void *state)
130{
131 return rs_tftp_get_tx_cnt(state);
132}
133
134static void *TFTPGetTx(void *state, uint64_t tx_id)
135{
136 return rs_tftp_get_tx(state, tx_id);
137}
138
b9cf49e9
CG
139/**
140 * \brief Return the state of a transaction in a given direction.
141 *
6a470a84 142 * In the case of the tftp protocol, the existence of a transaction
b9cf49e9
CG
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 */
152static int TFTPGetStateProgress(void *tx, uint8_t direction)
153{
154 return 1;
155}
156
b9cf49e9
CG
157void RegisterTFTPParsers(void)
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 (AppLayerProtoDetectConfProtoDetectionEnabled("udp", proto_name)) {
164
165 SCLogDebug("TFTP UDP protocol detection enabled.");
166
167 AppLayerProtoDetectRegisterProtocol(ALPROTO_TFTP, proto_name);
168
169 if (RunmodeIsUnittests()) {
6a470a84 170 SCLogDebug("Unittest mode, registering default configuration.");
b9cf49e9
CG
171 AppLayerProtoDetectPPRegister(IPPROTO_UDP, TFTP_DEFAULT_PORT,
172 ALPROTO_TFTP, 0, TFTP_MIN_FRAME_LEN,
173 STREAM_TOSERVER, TFTPProbingParser,
5ff50773 174 TFTPProbingParser);
b9cf49e9
CG
175 } else {
176 if (!AppLayerProtoDetectPPParseConfPorts("udp", IPPROTO_UDP,
177 proto_name, ALPROTO_TFTP,
178 0, TFTP_MIN_FRAME_LEN,
5ff50773 179 TFTPProbingParser, TFTPProbingParser)) {
6a470a84 180 SCLogDebug("No tftp app-layer configuration, enabling tftp"
b9cf49e9 181 " detection UDP detection on port %s.",
6a470a84 182 TFTP_DEFAULT_PORT);
b9cf49e9
CG
183 AppLayerProtoDetectPPRegister(IPPROTO_UDP,
184 TFTP_DEFAULT_PORT, ALPROTO_TFTP,
185 0, TFTP_MIN_FRAME_LEN,
186 STREAM_TOSERVER,TFTPProbingParser,
5ff50773 187 TFTPProbingParser);
b9cf49e9
CG
188 }
189 }
190 } else {
6a470a84 191 SCLogDebug("Protocol detector and parser disabled for TFTP.");
b9cf49e9
CG
192 return;
193 }
194
195 if (AppLayerParserConfParserEnabled("udp", proto_name)) {
196
197 SCLogDebug("Registering TFTP protocol parser.");
198
199 /* Register functions for state allocation and freeing. A
200 * state is allocated for every new TFTP flow. */
201 AppLayerParserRegisterStateFuncs(IPPROTO_UDP, ALPROTO_TFTP,
202 TFTPStateAlloc, TFTPStateFree);
203
204 /* Register request parser for parsing frame from server to client. */
205 AppLayerParserRegisterParser(IPPROTO_UDP, ALPROTO_TFTP,
206 STREAM_TOSERVER, TFTPParseRequest);
207
208 /* Register response parser for parsing frames from server to client. */
209 AppLayerParserRegisterParser(IPPROTO_UDP, ALPROTO_TFTP,
210 STREAM_TOCLIENT, TFTPParseResponse);
211
212 /* Register a function to be called by the application layer
213 * when a transaction is to be freed. */
214 AppLayerParserRegisterTxFreeFunc(IPPROTO_UDP, ALPROTO_TFTP,
215 TFTPStateTxFree);
216
b9cf49e9
CG
217 /* Register a function to return the current transaction count. */
218 AppLayerParserRegisterGetTxCnt(IPPROTO_UDP, ALPROTO_TFTP,
219 TFTPGetTxCnt);
220
221 /* Transaction handling. */
efc9a7a3 222 AppLayerParserRegisterStateProgressCompletionStatus(ALPROTO_TFTP, 1, 1);
b9cf49e9
CG
223 AppLayerParserRegisterGetStateProgressFunc(IPPROTO_UDP,
224 ALPROTO_TFTP,
225 TFTPGetStateProgress);
226 AppLayerParserRegisterGetTx(IPPROTO_UDP, ALPROTO_TFTP,
227 TFTPGetTx);
228
b9cf49e9
CG
229 AppLayerParserRegisterGetEventInfo(IPPROTO_UDP, ALPROTO_TFTP,
230 TFTPStateGetEventInfo);
e0debed0
VJ
231
232 AppLayerParserRegisterTxDataFunc(IPPROTO_UDP, ALPROTO_TFTP,
233 rs_tftp_get_tx_data);
b9cf49e9
CG
234 }
235 else {
236 SCLogDebug("TFTP protocol parsing disabled.");
237 }
b9cf49e9 238}