suricata
app-layer-dns-tcp-rust.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 #include "suricata-common.h"
19 #include "suricata.h"
20 
21 #include "app-layer-protos.h"
22 #include "app-layer-detect-proto.h"
23 #include "app-layer-parser.h"
24 #include "app-layer-dns-common.h"
25 
26 #include "util-unittest.h"
27 
28 #ifdef HAVE_RUST
29 
30 #include "app-layer-dns-tcp-rust.h"
31 #include "rust-dns-dns-gen.h"
32 
33 #ifdef UNITTESTS
34 static void RustDNSTCPParserRegisterTests(void);
35 #endif
36 
37 static int RustDNSTCPParseRequest(Flow *f, void *state,
38  AppLayerParserState *pstate, uint8_t *input, uint32_t input_len,
39  void *local_data, const uint8_t flags)
40 {
41  SCLogDebug("RustDNSTCPParseRequest");
42  return rs_dns_parse_request_tcp(f, state, pstate, input, input_len,
43  local_data);
44 }
45 
46 static int RustDNSTCPParseResponse(Flow *f, void *state,
47  AppLayerParserState *pstate, uint8_t *input, uint32_t input_len,
48  void *local_data, const uint8_t flags)
49 {
50  SCLogDebug("RustDNSTCPParseResponse");
51  return rs_dns_parse_response_tcp(f, state, pstate, input, input_len,
52  local_data);
53 }
54 
55 static uint16_t RustDNSTCPProbe(Flow *f, uint8_t *input, uint32_t len)
56 {
57  SCLogDebug("RustDNSTCPProbe");
58  if (len == 0 || len < sizeof(DNSHeader)) {
59  return ALPROTO_UNKNOWN;
60  }
61 
62  // Validate and return ALPROTO_FAILED if needed.
63  if (!rs_dns_probe_tcp(input, len)) {
64  return ALPROTO_FAILED;
65  }
66 
67  return ALPROTO_DNS;
68 }
69 
70 static int RustDNSGetAlstateProgress(void *tx, uint8_t direction)
71 {
72  return rs_dns_tx_get_alstate_progress(tx, direction);
73 }
74 
75 static uint64_t RustDNSGetTxCnt(void *alstate)
76 {
77  return rs_dns_state_get_tx_count(alstate);
78 }
79 
80 static void *RustDNSGetTx(void *alstate, uint64_t tx_id)
81 {
82  return rs_dns_state_get_tx(alstate, tx_id);
83 }
84 
85 static void RustDNSSetTxLogged(void *alstate, void *tx, LoggerId logged)
86 {
87  rs_dns_tx_set_logged(alstate, tx, logged);
88 }
89 
90 static LoggerId RustDNSGetTxLogged(void *alstate, void *tx)
91 {
92  return rs_dns_tx_get_logged(alstate, tx);
93 }
94 
95 static void RustDNSStateTransactionFree(void *state, uint64_t tx_id)
96 {
97  rs_dns_state_tx_free(state, tx_id);
98 }
99 
100 static DetectEngineState *RustDNSGetTxDetectState(void *tx)
101 {
102  return rs_dns_state_get_tx_detect_state(tx);
103 }
104 
105 static int RustDNSSetTxDetectState(void *tx,
107 {
108  rs_dns_state_set_tx_detect_state(tx, s);
109  return 0;
110 }
111 
112 static AppLayerDecoderEvents *RustDNSGetEvents(void *state, uint64_t id)
113 {
114  return rs_dns_state_get_events(state, id);
115 }
116 
117 void RegisterRustDNSTCPParsers(void)
118 {
119  const char *proto_name = "dns";
120 
121  /** DNS */
122  if (AppLayerProtoDetectConfProtoDetectionEnabled("tcp", proto_name)) {
124 
125  if (RunmodeIsUnittests()) {
126  AppLayerProtoDetectPPRegister(IPPROTO_TCP, "53", ALPROTO_DNS, 0,
127  sizeof(DNSHeader) + 2, STREAM_TOSERVER, RustDNSTCPProbe,
128  NULL);
129  } else {
130  int have_cfg = AppLayerProtoDetectPPParseConfPorts("tcp",
131  IPPROTO_TCP, proto_name, ALPROTO_DNS, 0,
132  sizeof(DNSHeader) + 2, RustDNSTCPProbe, RustDNSTCPProbe);
133  /* if we have no config, we enable the default port 53 */
134  if (!have_cfg) {
135  SCLogWarning(SC_ERR_DNS_CONFIG, "no DNS TCP config found, "
136  "enabling DNS detection on "
137  "port 53.");
138  AppLayerProtoDetectPPRegister(IPPROTO_TCP, "53", ALPROTO_DNS, 0,
139  sizeof(DNSHeader) + 2, STREAM_TOSERVER, RustDNSTCPProbe,
140  RustDNSTCPProbe);
141  }
142  }
143  } else {
144  SCLogInfo("Protocol detection and parser disabled for %s protocol.",
145  proto_name);
146  return;
147  }
148 
149  if (AppLayerParserConfParserEnabled("tcp", proto_name)) {
151  RustDNSTCPParseRequest);
153  RustDNSTCPParseResponse);
155  rs_dns_state_tcp_new, rs_dns_state_free);
157  RustDNSStateTransactionFree);
159  RustDNSGetEvents);
161  RustDNSGetTxDetectState, RustDNSSetTxDetectState);
162  AppLayerParserRegisterGetTx(IPPROTO_TCP, ALPROTO_DNS, RustDNSGetTx);
164  RustDNSGetTxCnt);
166  RustDNSGetTxLogged, RustDNSSetTxLogged);
168  RustDNSGetAlstateProgress);
170  rs_dns_state_progress_completion_status);
172 
173  /* This parser accepts gaps. */
176 
177  } else {
178  SCLogInfo("Parsed disabled for %s protocol. Protocol detection"
179  "still on.", proto_name);
180  }
181 
182 #ifdef UNITTESTS
184  RustDNSTCPParserRegisterTests);
185 #endif
186 
187  return;
188 }
189 
190 #ifdef UNITTESTS
191 
192 #include "util-unittest-helper.h"
193 
194 static int RustDNSTCPParserTestMultiRecord(void)
195 {
196  /* This is a buffer containing 20 DNS requests each prefixed by
197  * the request length for transport over TCP. It was generated with Scapy,
198  * where each request is:
199  * DNS(id=i, rd=1, qd=DNSQR(qname="%d.google.com" % i, qtype="A"))
200  * where i is 0 to 19.
201  */
202  uint8_t req[] = {
203  0x00, 0x1e, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01,
204  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x30,
205  0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
206  0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
207  0x00, 0x1e, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01,
208  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x31,
209  0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
210  0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
211  0x00, 0x1e, 0x00, 0x02, 0x01, 0x00, 0x00, 0x01,
212  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x32,
213  0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
214  0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
215  0x00, 0x1e, 0x00, 0x03, 0x01, 0x00, 0x00, 0x01,
216  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x33,
217  0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
218  0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
219  0x00, 0x1e, 0x00, 0x04, 0x01, 0x00, 0x00, 0x01,
220  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x34,
221  0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
222  0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
223  0x00, 0x1e, 0x00, 0x05, 0x01, 0x00, 0x00, 0x01,
224  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x35,
225  0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
226  0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
227  0x00, 0x1e, 0x00, 0x06, 0x01, 0x00, 0x00, 0x01,
228  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x36,
229  0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
230  0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
231  0x00, 0x1e, 0x00, 0x07, 0x01, 0x00, 0x00, 0x01,
232  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x37,
233  0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
234  0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
235  0x00, 0x1e, 0x00, 0x08, 0x01, 0x00, 0x00, 0x01,
236  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x38,
237  0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
238  0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
239  0x00, 0x1e, 0x00, 0x09, 0x01, 0x00, 0x00, 0x01,
240  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x39,
241  0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
242  0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
243  0x00, 0x1f, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x01,
244  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x31,
245  0x30, 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
246  0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00,
247  0x01, 0x00, 0x1f, 0x00, 0x0b, 0x01, 0x00, 0x00,
248  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
249  0x31, 0x31, 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
250  0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01,
251  0x00, 0x01, 0x00, 0x1f, 0x00, 0x0c, 0x01, 0x00,
252  0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
253  0x02, 0x31, 0x32, 0x06, 0x67, 0x6f, 0x6f, 0x67,
254  0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00,
255  0x01, 0x00, 0x01, 0x00, 0x1f, 0x00, 0x0d, 0x01,
256  0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
257  0x00, 0x02, 0x31, 0x33, 0x06, 0x67, 0x6f, 0x6f,
258  0x67, 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00,
259  0x00, 0x01, 0x00, 0x01, 0x00, 0x1f, 0x00, 0x0e,
260  0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
261  0x00, 0x00, 0x02, 0x31, 0x34, 0x06, 0x67, 0x6f,
262  0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d,
263  0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x1f, 0x00,
264  0x0f, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
265  0x00, 0x00, 0x00, 0x02, 0x31, 0x35, 0x06, 0x67,
266  0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63, 0x6f,
267  0x6d, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x1f,
268  0x00, 0x10, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00,
269  0x00, 0x00, 0x00, 0x00, 0x02, 0x31, 0x36, 0x06,
270  0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63,
271  0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
272  0x1f, 0x00, 0x11, 0x01, 0x00, 0x00, 0x01, 0x00,
273  0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x31, 0x37,
274  0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
275  0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
276  0x00, 0x1f, 0x00, 0x12, 0x01, 0x00, 0x00, 0x01,
277  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x31,
278  0x38, 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
279  0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00,
280  0x01, 0x00, 0x1f, 0x00, 0x13, 0x01, 0x00, 0x00,
281  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
282  0x31, 0x39, 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
283  0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01,
284  0x00, 0x01
285  };
286  size_t reqlen = sizeof(req);
287 
288  RSDNSState *state = rs_dns_state_new();
289 
290  Flow *f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 53);
291  FAIL_IF_NULL(f);
292  f->proto = IPPROTO_TCP;
293  f->alproto = ALPROTO_DNS;
294  f->alstate = state;
295 
296  FAIL_IF(RustDNSTCPParseRequest(f, f->alstate, NULL, req, reqlen,
297  NULL, STREAM_START) < 0);
298  FAIL_IF(rs_dns_state_get_tx_count(state) != 20);
299 
300  UTHFreeFlow(f);
301  PASS;
302 }
303 
304 static void RustDNSTCPParserRegisterTests(void)
305 {
306  UtRegisterTest("RustDNSTCPParserTestMultiRecord",
307  RustDNSTCPParserTestMultiRecord);
308 }
309 
310 #endif /* UNITTESTS */
311 
312 #endif /* HAVE_RUST */
uint16_t flags
#define SCLogDebug(...)
Definition: util-debug.h:335
void AppLayerParserRegisterOptionFlags(uint8_t ipproto, AppProto alproto, uint32_t flags)
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))
uint8_t proto
Definition: flow.h:346
LoggerId
int logged
#define PASS
Pass the test.
int AppLayerProtoDetectConfProtoDetectionEnabled(const char *ipproto, const char *alproto)
Given a protocol name, checks if proto detection is enabled in the conf file.
void AppLayerParserRegisterDetectStateFuncs(uint8_t ipproto, AppProto alproto, DetectEngineState *(*GetTxDetectState)(void *tx), int(*SetTxDetectState)(void *tx, DetectEngineState *))
#define FAIL_IF(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:71
void AppLayerParserRegisterLoggerFuncs(uint8_t ipproto, AppProto alproto, LoggerId(*StateGetTxLogged)(void *, void *), void(*StateSetTxLogged)(void *, void *, LoggerId))
void * alstate
Definition: flow.h:436
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...
Flow * UTHBuildFlow(int family, const char *src, const char *dst, Port sp, Port dp)
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 UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
#define STREAM_TOCLIENT
Definition: stream.h:32
void AppLayerParserRegisterGetStateProgressCompletionStatus(AppProto alproto, int(*StateGetProgressCompletionStatus)(uint8_t direction))
int RunmodeIsUnittests(void)
Definition: suricata.c:261
#define SCLogWarning(err_code,...)
Macro used to log WARNING messages.
Definition: util-debug.h:281
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:254
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))
#define STREAM_START
Definition: stream.h:29
#define STREAM_TOSERVER
Definition: stream.h:31
#define APP_LAYER_PARSER_OPT_ACCEPT_GAPS
struct RSDNSState_ RSDNSState
void RegisterRustDNSTCPParsers(void)
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
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 *))
uint8_t len
AppProto alproto
application level protocol
Definition: flow.h:407
Flow data structure.
Definition: flow.h:327
void UTHFreeFlow(Flow *flow)
void DNSAppLayerRegisterGetEventInfo(uint8_t ipproto, AppProto alproto)
void AppLayerParserRegisterTxFreeFunc(uint8_t ipproto, AppProto alproto, void(*StateTransactionFree)(void *, uint64_t))