suricata
util-lua-dns.c
Go to the documentation of this file.
1 /* Copyright (C) 2014 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 
19 /**
20  * \file
21  *
22  * \author Eric Leblond <eric@regit.org>
23  *
24  */
25 
26 #include "suricata-common.h"
27 #include "debug.h"
28 #include "detect.h"
29 #include "pkt-var.h"
30 #include "conf.h"
31 
32 #include "threads.h"
33 #include "threadvars.h"
34 #include "tm-threads.h"
35 
36 #include "util-print.h"
37 #include "util-unittest.h"
38 
39 #include "util-debug.h"
40 
41 #include "output.h"
42 #include "app-layer-dns-common.h"
43 #include "app-layer.h"
44 #include "app-layer-parser.h"
45 #include "util-privs.h"
46 #include "util-buffer.h"
47 #include "util-proto-name.h"
48 #include "util-logopenfile.h"
49 #include "util-time.h"
50 
51 #ifdef HAVE_LUA
52 
53 #include <lua.h>
54 #include <lualib.h>
55 #include <lauxlib.h>
56 
57 #include "util-lua.h"
58 #include "util-lua-common.h"
59 #include "util-lua-dns.h"
60 
61 #ifdef HAVE_RUST
62 #include "rust-dns-dns-gen.h"
63 #include "rust-dns-lua-gen.h"
64 #endif
65 
66 static int DnsGetDnsRrname(lua_State *luastate)
67 {
68  if (!(LuaStateNeedProto(luastate, ALPROTO_DNS)))
69  return LuaCallbackError(luastate, "error: protocol not dns");
70 #ifdef HAVE_RUST
71  RSDNSTransaction *tx = LuaStateGetTX(luastate);
72  if (tx == NULL) {
73  return LuaCallbackError(luastate, "internal error: no tx");
74  }
75  return rs_dns_lua_get_rrname(luastate, tx);
76 #else
77  DNSTransaction *tx = LuaStateGetTX(luastate);
78  if (tx == NULL)
79  return LuaCallbackError(luastate, "internal error: no tx");
80 
81  DNSQueryEntry *query = NULL;
82  TAILQ_FOREACH(query, &tx->query_list, next) {
83  char *c;
84  size_t input_len;
85  c = BytesToString((uint8_t *)((uint8_t *)query + sizeof(DNSQueryEntry)), query->len);
86  if (c != NULL) {
87  int ret;
88  input_len = strlen(c);
89  /* sanity check */
90  if (input_len > (size_t)(2 * query->len)) {
91  SCFree(c);
92  return LuaCallbackError(luastate, "invalid length");
93  }
94  ret = LuaPushStringBuffer(luastate, (uint8_t *)c, input_len);
95  SCFree(c);
96  return ret;
97  }
98  }
99  return LuaCallbackError(luastate, "no query");
100 #endif
101 }
102 
103 static int DnsGetTxid(lua_State *luastate)
104 {
105  if (!(LuaStateNeedProto(luastate, ALPROTO_DNS)))
106  return LuaCallbackError(luastate, "error: protocol not dns");
107 #ifdef HAVE_RUST
108  RSDNSTransaction *tx = LuaStateGetTX(luastate);
109  if (tx == NULL) {
110  return LuaCallbackError(luastate, "internal error: no tx");
111  }
112  rs_dns_lua_get_tx_id(luastate, tx);
113 #else
114  DNSTransaction *tx = LuaStateGetTX(luastate);
115  if (tx == NULL)
116  return LuaCallbackError(luastate, "internal error: no tx");
117 
118  lua_pushinteger(luastate, tx->tx_id);
119 #endif
120  return 1;
121 }
122 
123 static int DnsGetRcode(lua_State *luastate)
124 {
125  if (!(LuaStateNeedProto(luastate, ALPROTO_DNS)))
126  return LuaCallbackError(luastate, "error: protocol not dns");
127  uint16_t rcode = 0;
128 #ifdef HAVE_RUST
129  RSDNSTransaction *tx = LuaStateGetTX(luastate);
130  if (tx == NULL) {
131  return LuaCallbackError(luastate, "internal error: no tx");
132  }
133  uint16_t flags = rs_dns_tx_get_response_flags(tx);
134  rcode = flags & 0x000f;
135 #else
136  DNSTransaction *tx = LuaStateGetTX(luastate);
137  if (tx == NULL)
138  return LuaCallbackError(luastate, "internal error: no tx");
139  rcode = tx->rcode;
140 #endif
141  if (rcode) {
142  char rcode_str[16] = "";
143  DNSCreateRcodeString(rcode, rcode_str, sizeof(rcode_str));
144  return LuaPushStringBuffer(luastate, (const uint8_t *)rcode_str, strlen(rcode_str));
145  } else {
146  return 0;
147  }
148 }
149 
150 static int DnsGetRecursionDesired(lua_State *luastate)
151 {
152  if (!(LuaStateNeedProto(luastate, ALPROTO_DNS)))
153  return LuaCallbackError(luastate, "error: protocol not dns");
154 #ifdef HAVE_RUST
155  RSDNSTransaction *tx = LuaStateGetTX(luastate);
156  if (tx == NULL) {
157  return LuaCallbackError(luastate, "internal error: no tx");
158  }
159  uint16_t flags = rs_dns_tx_get_response_flags(tx);
160  int recursion_desired = flags & 0x0080 ? 1 : 0;
161  lua_pushboolean(luastate, recursion_desired);
162 #else
163  DNSTransaction *tx = LuaStateGetTX(luastate);
164  if (tx == NULL)
165  return LuaCallbackError(luastate, "internal error: no tx");
166 
167  lua_pushboolean(luastate, tx->recursion_desired);
168 #endif
169  return 1;
170 }
171 
172 static int DnsGetQueryTable(lua_State *luastate)
173 {
174  if (!(LuaStateNeedProto(luastate, ALPROTO_DNS)))
175  return LuaCallbackError(luastate, "error: protocol not dns");
176 #ifdef HAVE_RUST
177  RSDNSTransaction *tx = LuaStateGetTX(luastate);
178  if (tx == NULL) {
179  return LuaCallbackError(luastate, "internal error: no tx");
180  }
181  return rs_dns_lua_get_query_table(luastate, tx);
182 #else
183  DNSTransaction *tx = LuaStateGetTX(luastate);
184  if (tx == NULL)
185  return LuaCallbackError(luastate, "internal error: no tx");
186 
187  uint32_t u = 0;
188  lua_newtable(luastate);
189  DNSQueryEntry *query = NULL;
190  TAILQ_FOREACH(query, &tx->query_list, next) {
191  lua_pushinteger(luastate, u++);
192 
193  lua_newtable(luastate);
194  char record[16] = "";
195  DNSCreateTypeString(query->type, record, sizeof(record));
196  lua_pushstring(luastate, "type");
197  lua_pushstring(luastate, record);
198  lua_settable(luastate, -3);
199 
200  {
201  char *c;
202  size_t input_len;
203  c = BytesToString((uint8_t *)((uint8_t *)query + sizeof(DNSQueryEntry)), query->len);
204  if (c != NULL) {
205  input_len = strlen(c);
206  /* sanity check */
207  if (input_len > (size_t)(2 * query->len)) {
208  SCFree(c);
209  return LuaCallbackError(luastate, "invalid length");
210  }
211  lua_pushstring(luastate, "rrname");
212  LuaPushStringBuffer(luastate, (uint8_t *)c, input_len);
213  lua_settable(luastate, -3);
214  SCFree(c);
215  }
216  }
217 
218 
219  lua_settable(luastate, -3);
220  }
221 
222  return 1;
223 #endif
224 }
225 
226 static int DnsGetAnswerTable(lua_State *luastate)
227 {
228  if (!(LuaStateNeedProto(luastate, ALPROTO_DNS)))
229  return LuaCallbackError(luastate, "error: protocol not dns");
230 #ifdef HAVE_RUST
231  RSDNSTransaction *tx = LuaStateGetTX(luastate);
232  return rs_dns_lua_get_answer_table(luastate, tx);
233 #else
234  DNSTransaction *tx = LuaStateGetTX(luastate);
235  if (tx == NULL)
236  return LuaCallbackError(luastate, "internal error: no tx");
237 
238  uint32_t u = 0;
239  lua_newtable(luastate);
240  DNSAnswerEntry *answer = NULL;
241  TAILQ_FOREACH(answer, &tx->answer_list, next) {
242  lua_pushinteger(luastate, u++);
243 
244  lua_newtable(luastate);
245  char record[16] = "";
246  DNSCreateTypeString(answer->type, record, sizeof(record));
247  lua_pushstring(luastate, "type");
248  lua_pushstring(luastate, record);
249  lua_settable(luastate, -3);
250 
251  lua_pushstring(luastate, "ttl");
252  lua_pushinteger(luastate, answer->ttl);
253  lua_settable(luastate, -3);
254 
255  {
256  uint8_t *ptr = (uint8_t *)((uint8_t *)answer + sizeof(DNSAnswerEntry));
257  lua_pushstring(luastate, "rrname");
258  LuaPushStringBuffer(luastate, ptr, answer->fqdn_len);
259  lua_settable(luastate, -3);
260 
261  ptr = (uint8_t *)((uint8_t *)answer + sizeof(DNSAnswerEntry) + answer->fqdn_len);
262  if (answer->type == DNS_RECORD_TYPE_A) {
263  char a[16] = "";
264  if (answer->data_len == 4) {
265  PrintInet(AF_INET, (const void *)ptr, a, sizeof(a));
266  }
267  lua_pushstring(luastate, "addr");
268  LuaPushStringBuffer(luastate, (uint8_t *)a, strlen(a));
269  lua_settable(luastate, -3);
270  } else if (answer->type == DNS_RECORD_TYPE_AAAA) {
271  char a[46] = "";
272  if (answer->data_len == 16) {
273  PrintInet(AF_INET6, (const void *)ptr, a, sizeof(a));
274  }
275  lua_pushstring(luastate, "addr");
276  LuaPushStringBuffer(luastate, (uint8_t *)a, strlen(a));
277  lua_settable(luastate, -3);
278  } else if (answer->data_len == 0) {
279  /* not setting 'addr' */
280  } else {
281  lua_pushstring(luastate, "addr");
282  LuaPushStringBuffer(luastate, (uint8_t *)ptr, answer->data_len);
283  lua_settable(luastate, -3);
284  }
285  }
286 
287  lua_settable(luastate, -3);
288  }
289 
290  return 1;
291 #endif
292 }
293 
294 static int DnsGetAuthorityTable(lua_State *luastate)
295 {
296  if (!(LuaStateNeedProto(luastate, ALPROTO_DNS)))
297  return LuaCallbackError(luastate, "error: protocol not dns");
298 #ifdef HAVE_RUST
299  RSDNSTransaction *tx = LuaStateGetTX(luastate);
300  return rs_dns_lua_get_authority_table(luastate, tx);
301 #else
302  DNSTransaction *tx = LuaStateGetTX(luastate);
303  if (tx == NULL)
304  return LuaCallbackError(luastate, "internal error: no tx");
305 
306  uint32_t u = 0;
307  lua_newtable(luastate);
308  DNSAnswerEntry *answer = NULL;
309  TAILQ_FOREACH(answer, &tx->authority_list, next) {
310  lua_pushinteger(luastate, u++);
311 
312  lua_newtable(luastate);
313  char record[16] = "";
314  DNSCreateTypeString(answer->type, record, sizeof(record));
315  lua_pushstring(luastate, "type");
316  lua_pushstring(luastate, record);
317  lua_settable(luastate, -3);
318 
319  lua_pushstring(luastate, "ttl");
320  lua_pushinteger(luastate, answer->ttl);
321  lua_settable(luastate, -3);
322 
323  {
324  char *c;
325  size_t input_len;
326  c = BytesToString((uint8_t *)((uint8_t *)answer + sizeof(DNSAnswerEntry)), answer->fqdn_len);
327  if (c != NULL) {
328  input_len = strlen(c);
329  /* sanity check */
330  if (input_len > (size_t)(2 * answer->fqdn_len)) {
331  SCFree(c);
332  return LuaCallbackError(luastate, "invalid length");
333  }
334  lua_pushstring(luastate, "rrname");
335  LuaPushStringBuffer(luastate, (uint8_t *)c, input_len);
336  lua_settable(luastate, -3);
337  SCFree(c);
338  }
339  }
340 
341 
342  lua_settable(luastate, -3);
343  }
344 
345  return 1;
346 #endif
347 }
348 
349 
350 /** \brief register http lua extensions in a luastate */
351 int LuaRegisterDnsFunctions(lua_State *luastate)
352 {
353  /* registration of the callbacks */
354  lua_pushcfunction(luastate, DnsGetDnsRrname);
355  lua_setglobal(luastate, "DnsGetDnsRrname");
356 
357  lua_pushcfunction(luastate, DnsGetQueryTable);
358  lua_setglobal(luastate, "DnsGetQueries");
359 
360  lua_pushcfunction(luastate, DnsGetAnswerTable);
361  lua_setglobal(luastate, "DnsGetAnswers");
362 
363  lua_pushcfunction(luastate, DnsGetAuthorityTable);
364  lua_setglobal(luastate, "DnsGetAuthorities");
365 
366  lua_pushcfunction(luastate, DnsGetTxid);
367  lua_setglobal(luastate, "DnsGetTxid");
368 
369  lua_pushcfunction(luastate, DnsGetRcode);
370  lua_setglobal(luastate, "DnsGetRcode");
371 
372  lua_pushcfunction(luastate, DnsGetRecursionDesired);
373  lua_setglobal(luastate, "DnsGetRecursionDesired");
374  return 0;
375 }
376 
377 #endif /* HAVE_LUA */
struct DNSAnswerEntry_ DNSAnswerEntry
DNS Answer storage. Stored in TX list.
uint16_t flags
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:350
struct HtpBodyChunk_ * next
DNS Transaction, request/reply with same TX id.
void DNSCreateRcodeString(uint8_t rcode, char *str, size_t str_size)
DNS Answer storage. Stored in TX list.
DNS Query storage. Stored in TX list.
#define DNS_RECORD_TYPE_A
const char * PrintInet(int af, const void *src, char *dst, socklen_t size)
Definition: util-print.c:267
char * BytesToString(const uint8_t *bytes, size_t nbytes)
Turn byte array into string.
Definition: util-byte.c:40
#define DNS_RECORD_TYPE_AAAA
#define SCFree(a)
Definition: util-mem.h:236
struct RSDNSTransaction_ RSDNSTransaction
void DNSCreateTypeString(uint16_t type, char *str, size_t str_size)