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 *state, uint64_t id)
114 {
115  return rs_dns_state_get_events(state, id);
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);
173 
174  /* This parser accepts gaps. */
177 
178  } else {
179  SCLogInfo("Parsed disabled for %s protocol. Protocol detection"
180  "still on.", proto_name);
181  }
182 
183 #ifdef UNITTESTS
185  RustDNSTCPParserRegisterTests);
186 #endif
187 
188  return;
189 }
190 
191 #ifdef UNITTESTS
192 
193 #include "util-unittest-helper.h"
194 
195 static int RustDNSTCPParserTestMultiRecord(void)
196 {
197  /* This is a buffer containing 20 DNS requests each prefixed by
198  * the request length for transport over TCP. It was generated with Scapy,
199  * where each request is:
200  * DNS(id=i, rd=1, qd=DNSQR(qname="%d.google.com" % i, qtype="A"))
201  * where i is 0 to 19.
202  */
203  uint8_t req[] = {
204  0x00, 0x1e, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01,
205  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x30,
206  0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
207  0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
208  0x00, 0x1e, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01,
209  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x31,
210  0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
211  0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
212  0x00, 0x1e, 0x00, 0x02, 0x01, 0x00, 0x00, 0x01,
213  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x32,
214  0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
215  0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
216  0x00, 0x1e, 0x00, 0x03, 0x01, 0x00, 0x00, 0x01,
217  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x33,
218  0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
219  0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
220  0x00, 0x1e, 0x00, 0x04, 0x01, 0x00, 0x00, 0x01,
221  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x34,
222  0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
223  0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
224  0x00, 0x1e, 0x00, 0x05, 0x01, 0x00, 0x00, 0x01,
225  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x35,
226  0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
227  0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
228  0x00, 0x1e, 0x00, 0x06, 0x01, 0x00, 0x00, 0x01,
229  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x36,
230  0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
231  0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
232  0x00, 0x1e, 0x00, 0x07, 0x01, 0x00, 0x00, 0x01,
233  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x37,
234  0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
235  0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
236  0x00, 0x1e, 0x00, 0x08, 0x01, 0x00, 0x00, 0x01,
237  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x38,
238  0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
239  0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
240  0x00, 0x1e, 0x00, 0x09, 0x01, 0x00, 0x00, 0x01,
241  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x39,
242  0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
243  0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
244  0x00, 0x1f, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x01,
245  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x31,
246  0x30, 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
247  0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00,
248  0x01, 0x00, 0x1f, 0x00, 0x0b, 0x01, 0x00, 0x00,
249  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
250  0x31, 0x31, 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
251  0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01,
252  0x00, 0x01, 0x00, 0x1f, 0x00, 0x0c, 0x01, 0x00,
253  0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
254  0x02, 0x31, 0x32, 0x06, 0x67, 0x6f, 0x6f, 0x67,
255  0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00,
256  0x01, 0x00, 0x01, 0x00, 0x1f, 0x00, 0x0d, 0x01,
257  0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
258  0x00, 0x02, 0x31, 0x33, 0x06, 0x67, 0x6f, 0x6f,
259  0x67, 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00,
260  0x00, 0x01, 0x00, 0x01, 0x00, 0x1f, 0x00, 0x0e,
261  0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
262  0x00, 0x00, 0x02, 0x31, 0x34, 0x06, 0x67, 0x6f,
263  0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d,
264  0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x1f, 0x00,
265  0x0f, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
266  0x00, 0x00, 0x00, 0x02, 0x31, 0x35, 0x06, 0x67,
267  0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63, 0x6f,
268  0x6d, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x1f,
269  0x00, 0x10, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00,
270  0x00, 0x00, 0x00, 0x00, 0x02, 0x31, 0x36, 0x06,
271  0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03, 0x63,
272  0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
273  0x1f, 0x00, 0x11, 0x01, 0x00, 0x00, 0x01, 0x00,
274  0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x31, 0x37,
275  0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x03,
276  0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01,
277  0x00, 0x1f, 0x00, 0x12, 0x01, 0x00, 0x00, 0x01,
278  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x31,
279  0x38, 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
280  0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00,
281  0x01, 0x00, 0x1f, 0x00, 0x13, 0x01, 0x00, 0x00,
282  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
283  0x31, 0x39, 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
284  0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01,
285  0x00, 0x01
286  };
287  size_t reqlen = sizeof(req);
288 
289  RSDNSState *state = rs_dns_state_new();
290 
291  Flow *f = UTHBuildFlow(AF_INET, "1.2.3.4", "1.2.3.5", 1024, 53);
292  FAIL_IF_NULL(f);
293  f->proto = IPPROTO_TCP;
294  f->alproto = ALPROTO_DNS;
295  f->alstate = state;
296 
297  FAIL_IF(RustDNSTCPParseRequest(f, f->alstate, NULL, req, reqlen,
298  NULL, STREAM_START) < 0);
299  FAIL_IF(rs_dns_state_get_tx_count(state) != 20);
300 
301  UTHFreeFlow(f);
302  PASS;
303 }
304 
305 static void RustDNSTCPParserRegisterTests(void)
306 {
307  UtRegisterTest("RustDNSTCPParserTestMultiRecord",
308  RustDNSTCPParserTestMultiRecord);
309 }
310 
311 #endif /* UNITTESTS */
312 
313 #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
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: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:259
#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: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))