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