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 direction,
56  uint8_t *input, uint32_t len, uint8_t *rdir)
57 {
58  SCLogDebug("RustDNSTCPProbe");
59  if (len == 0 || len < sizeof(DNSHeader)) {
60  return ALPROTO_UNKNOWN;
61  }
62 
63  // Validate and return ALPROTO_FAILED if needed.
64  if (!rs_dns_probe_tcp(input, len)) {
65  return ALPROTO_FAILED;
66  }
67 
68  return ALPROTO_DNS;
69 }
70 
71 static int RustDNSGetAlstateProgress(void *tx, uint8_t direction)
72 {
73  return rs_dns_tx_get_alstate_progress(tx, direction);
74 }
75 
76 static uint64_t RustDNSGetTxCnt(void *alstate)
77 {
78  return rs_dns_state_get_tx_count(alstate);
79 }
80 
81 static void *RustDNSGetTx(void *alstate, uint64_t tx_id)
82 {
83  return rs_dns_state_get_tx(alstate, tx_id);
84 }
85 
86 static void RustDNSSetTxLogged(void *alstate, void *tx, LoggerId logged)
87 {
88  rs_dns_tx_set_logged(alstate, tx, logged);
89 }
90 
91 static LoggerId RustDNSGetTxLogged(void *alstate, void *tx)
92 {
93  return rs_dns_tx_get_logged(alstate, tx);
94 }
95 
96 static void RustDNSStateTransactionFree(void *state, uint64_t tx_id)
97 {
98  rs_dns_state_tx_free(state, tx_id);
99 }
100 
101 static DetectEngineState *RustDNSGetTxDetectState(void *tx)
102 {
103  return rs_dns_state_get_tx_detect_state(tx);
104 }
105 
106 static int RustDNSSetTxDetectState(void *tx,
108 {
109  rs_dns_state_set_tx_detect_state(tx, s);
110  return 0;
111 }
112 
113 static AppLayerDecoderEvents *RustDNSGetEvents(void *tx)
114 {
115  return rs_dns_state_get_events(tx);
116 }
117 
118 void RegisterRustDNSTCPParsers(void)
119 {
120  const char *proto_name = "dns";
121 
122  /** DNS */
123  if (AppLayerProtoDetectConfProtoDetectionEnabled("tcp", proto_name)) {
125 
126  if (RunmodeIsUnittests()) {
127  AppLayerProtoDetectPPRegister(IPPROTO_TCP, "53", ALPROTO_DNS, 0,
128  sizeof(DNSHeader) + 2, STREAM_TOSERVER, RustDNSTCPProbe,
129  NULL);
130  } else {
131  int have_cfg = AppLayerProtoDetectPPParseConfPorts("tcp",
132  IPPROTO_TCP, proto_name, ALPROTO_DNS, 0,
133  sizeof(DNSHeader) + 2, RustDNSTCPProbe, RustDNSTCPProbe);
134  /* if we have no config, we enable the default port 53 */
135  if (!have_cfg) {
136  SCLogWarning(SC_ERR_DNS_CONFIG, "no DNS TCP config found, "
137  "enabling DNS detection on "
138  "port 53.");
139  AppLayerProtoDetectPPRegister(IPPROTO_TCP, "53", ALPROTO_DNS, 0,
140  sizeof(DNSHeader) + 2, STREAM_TOSERVER, RustDNSTCPProbe,
141  RustDNSTCPProbe);
142  }
143  }
144  } else {
145  SCLogInfo("Protocol detection and parser disabled for %s protocol.",
146  proto_name);
147  return;
148  }
149 
150  if (AppLayerParserConfParserEnabled("tcp", proto_name)) {
152  RustDNSTCPParseRequest);
154  RustDNSTCPParseResponse);
156  rs_dns_state_tcp_new, rs_dns_state_free);
158  RustDNSStateTransactionFree);
160  RustDNSGetEvents);
162  RustDNSGetTxDetectState, RustDNSSetTxDetectState);
163  AppLayerParserRegisterGetTx(IPPROTO_TCP, ALPROTO_DNS, RustDNSGetTx);
165  RustDNSGetTxCnt);
167  RustDNSGetTxLogged, RustDNSSetTxLogged);
169  RustDNSGetAlstateProgress);
171  rs_dns_state_progress_completion_status);
174 
175  /* This parser accepts gaps. */
178 
179  } else {
180  SCLogInfo("Parsed disabled for %s protocol. Protocol detection"
181  "still on.", proto_name);
182  }
183 
184 #ifdef UNITTESTS
186  RustDNSTCPParserRegisterTests);
187 #endif
188 
189  return;
190 }
191 
192 #ifdef UNITTESTS
193 
194 #include "util-unittest-helper.h"
195 
196 static int RustDNSTCPParserTestMultiRecord(void)
197 {
198  /* This is a buffer containing 20 DNS requests each prefixed by
199  * the request length for transport over TCP. It was generated with Scapy,
200  * where each request is:
201  * DNS(id=i, rd=1, qd=DNSQR(qname="%d.google.com" % i, qtype="A"))
202  * where i is 0 to 19.
203  */
204  uint8_t req[] = {
205  0x00, 0x1e, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01,
206  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x30,
207  0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
208  0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
209  0x00, 0x1e, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01,
210  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x31,
211  0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
212  0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
213  0x00, 0x1e, 0x00, 0x02, 0x01, 0x00, 0x00, 0x01,
214  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x32,
215  0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
216  0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
217  0x00, 0x1e, 0x00, 0x03, 0x01, 0x00, 0x00, 0x01,
218  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x33,
219  0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
220  0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
221  0x00, 0x1e, 0x00, 0x04, 0x01, 0x00, 0x00, 0x01,
222  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x34,
223  0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
224  0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
225  0x00, 0x1e, 0x00, 0x05, 0x01, 0x00, 0x00, 0x01,
226  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x35,
227  0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
228  0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
229  0x00, 0x1e, 0x00, 0x06, 0x01, 0x00, 0x00, 0x01,
230  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x36,
231  0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
232  0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
233  0x00, 0x1e, 0x00, 0x07, 0x01, 0x00, 0x00, 0x01,
234  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x37,
235  0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
236  0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
237  0x00, 0x1e, 0x00, 0x08, 0x01, 0x00, 0x00, 0x01,
238  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x38,
239  0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
240  0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
241  0x00, 0x1e, 0x00, 0x09, 0x01, 0x00, 0x00, 0x01,
242  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x39,
243  0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
244  0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
245  0x00, 0x1f, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x01,
246  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x31,
247  0x30, 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
248  0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00,
249  0x01, 0x00, 0x1f, 0x00, 0x0b, 0x01, 0x00, 0x00,
250  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
251  0x31, 0x31, 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
252  0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01,
253  0x00, 0x01, 0x00, 0x1f, 0x00, 0x0c, 0x01, 0x00,
254  0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
255  0x02, 0x31, 0x32, 0x06, 0x67, 0x6f, 0x6f, 0x67,
256  0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00,
257  0x01, 0x00, 0x01, 0x00, 0x1f, 0x00, 0x0d, 0x01,
258  0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
259  0x00, 0x02, 0x31, 0x33, 0x06, 0x67, 0x6f, 0x6f,
260  0x67, 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00,
261  0x00, 0x01, 0x00, 0x01, 0x00, 0x1f, 0x00, 0x0e,
262  0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
263  0x00, 0x00, 0x02, 0x31, 0x34, 0x06, 0x67, 0x6f,
264  0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d,
265  0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x1f, 0x00,
266  0x0f, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
267  0x00, 0x00, 0x00, 0x02, 0x31, 0x35, 0x06, 0x67,
268  0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63, 0x6f,
269  0x6d, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x1f,
270  0x00, 0x10, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00,
271  0x00, 0x00, 0x00, 0x00, 0x02, 0x31, 0x36, 0x06,
272  0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63,
273  0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
274  0x1f, 0x00, 0x11, 0x01, 0x00, 0x00, 0x01, 0x00,
275  0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x31, 0x37,
276  0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
277  0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
278  0x00, 0x1f, 0x00, 0x12, 0x01, 0x00, 0x00, 0x01,
279  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x31,
280  0x38, 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
281  0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00,
282  0x01, 0x00, 0x1f, 0x00, 0x13, 0x01, 0x00, 0x00,
283  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
284  0x31, 0x39, 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
285  0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01,
286  0x00, 0x01
287  };
288  size_t reqlen = sizeof(req);
289 
290  RSDNSState *state = rs_dns_state_new();
291 
292  Flow *f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 53);
293  FAIL_IF_NULL(f);
294  f->proto = IPPROTO_TCP;
295  f->alproto = ALPROTO_DNS;
296  f->alstate = state;
297 
298  FAIL_IF(RustDNSTCPParseRequest(f, f->alstate, NULL, req, reqlen,
299  NULL, STREAM_START) < 0);
300  FAIL_IF(rs_dns_state_get_tx_count(state) != 20);
301 
302  UTHFreeFlow(f);
303  PASS;
304 }
305 
306 static void RustDNSTCPParserRegisterTests(void)
307 {
308  UtRegisterTest("RustDNSTCPParserTestMultiRecord",
309  RustDNSTCPParserTestMultiRecord);
310 }
311 
312 #endif /* UNITTESTS */
313 
314 #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:344
LoggerId
void DNSAppLayerRegisterGetEventInfoById(uint8_t ipproto, AppProto alproto)
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 AppLayerParserRegisterGetEventsFunc(uint8_t ipproto, AppProto alproto, AppLayerDecoderEvents *(*StateGetEvents)(void *))
void AppLayerParserRegisterLoggerFuncs(uint8_t ipproto, AppProto alproto, LoggerId(*StateGetTxLogged)(void *, void *), void(*StateSetTxLogged)(void *, void *, LoggerId))
void * alstate
Definition: flow.h:438
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:265
#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 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:409
Flow data structure.
Definition: flow.h:325
void UTHFreeFlow(Flow *flow)
void DNSAppLayerRegisterGetEventInfo(uint8_t ipproto, AppProto alproto)
void AppLayerParserRegisterTxFreeFunc(uint8_t ipproto, AppProto alproto, void(*StateTransactionFree)(void *, uint64_t))