From: Victor Julien Date: Fri, 5 Jun 2015 06:53:47 +0000 (+0200) Subject: lua: dns extensions X-Git-Tag: suricata-3.0RC1~261 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a1e50b3138b59c667120b19997c5a7e40499b0e1;p=thirdparty%2Fsuricata.git lua: dns extensions Add DNS lua calls for getting queries, answers, authorities. Also rcode and recusion desired flags. --- diff --git a/src/util-lua-dns.c b/src/util-lua-dns.c index 8ac0688d01..dcebc6a132 100644 --- a/src/util-lua-dns.c +++ b/src/util-lua-dns.c @@ -88,12 +88,233 @@ static int DnsGetDnsRrname(lua_State *luastate) return LuaCallbackError(luastate, "no query"); } +static int DnsGetTxid(lua_State *luastate) +{ + if (!(LuaStateNeedProto(luastate, ALPROTO_DNS))) + return LuaCallbackError(luastate, "error: protocol not dns"); + + DNSTransaction *tx = LuaStateGetTX(luastate); + if (tx == NULL) + return LuaCallbackError(luastate, "internal error: no tx"); + + lua_pushinteger(luastate, tx->tx_id); + return 1; +} + +static int DnsGetRcode(lua_State *luastate) +{ + if (!(LuaStateNeedProto(luastate, ALPROTO_DNS))) + return LuaCallbackError(luastate, "error: protocol not dns"); + + DNSTransaction *tx = LuaStateGetTX(luastate); + if (tx == NULL) + return LuaCallbackError(luastate, "internal error: no tx"); + + if (tx->rcode) { + char rcode[16] = ""; + DNSCreateRcodeString(tx->rcode, rcode, sizeof(rcode)); + return LuaPushStringBuffer(luastate, (const uint8_t *)rcode, strlen(rcode)); + } else { + return 0; + } +} + +static int DnsGetRecursionDesired(lua_State *luastate) +{ + if (!(LuaStateNeedProto(luastate, ALPROTO_DNS))) + return LuaCallbackError(luastate, "error: protocol not dns"); + + DNSTransaction *tx = LuaStateGetTX(luastate); + if (tx == NULL) + return LuaCallbackError(luastate, "internal error: no tx"); + + lua_pushboolean(luastate, tx->recursion_desired); + return 1; +} + +static int DnsGetQueryTable(lua_State *luastate) +{ + if (!(LuaStateNeedProto(luastate, ALPROTO_DNS))) + return LuaCallbackError(luastate, "error: protocol not dns"); + + DNSTransaction *tx = LuaStateGetTX(luastate); + if (tx == NULL) + return LuaCallbackError(luastate, "internal error: no tx"); + + uint32_t u = 0; + lua_newtable(luastate); + DNSQueryEntry *query = NULL; + TAILQ_FOREACH(query, &tx->query_list, next) { + lua_pushinteger(luastate, u++); + + lua_newtable(luastate); + char record[16] = ""; + DNSCreateTypeString(query->type, record, sizeof(record)); + lua_pushstring(luastate, "type"); + lua_pushstring(luastate, record); + lua_settable(luastate, -3); + + { + char *c; + size_t input_len; + c = BytesToString((uint8_t *)((uint8_t *)query + sizeof(DNSQueryEntry)), query->len); + if (c != NULL) { + input_len = strlen(c); + /* sanity check */ + if (input_len > (size_t)(2 * query->len)) { + SCFree(c); + return LuaCallbackError(luastate, "invalid length"); + } + lua_pushstring(luastate, "rrname"); + LuaPushStringBuffer(luastate, (uint8_t *)c, input_len); + lua_settable(luastate, -3); + SCFree(c); + } + } + + + lua_settable(luastate, -3); + } + + return 1; +} + +static int DnsGetAnswerTable(lua_State *luastate) +{ + if (!(LuaStateNeedProto(luastate, ALPROTO_DNS))) + return LuaCallbackError(luastate, "error: protocol not dns"); + + DNSTransaction *tx = LuaStateGetTX(luastate); + if (tx == NULL) + return LuaCallbackError(luastate, "internal error: no tx"); + + uint32_t u = 0; + lua_newtable(luastate); + DNSAnswerEntry *answer = NULL; + TAILQ_FOREACH(answer, &tx->answer_list, next) { + lua_pushinteger(luastate, u++); + + lua_newtable(luastate); + char record[16] = ""; + DNSCreateTypeString(answer->type, record, sizeof(record)); + lua_pushstring(luastate, "type"); + lua_pushstring(luastate, record); + lua_settable(luastate, -3); + + lua_pushstring(luastate, "ttl"); + lua_pushinteger(luastate, answer->ttl); + lua_settable(luastate, -3); + + { + uint8_t *ptr = (uint8_t *)((uint8_t *)answer + sizeof(DNSAnswerEntry)); + lua_pushstring(luastate, "rrname"); + LuaPushStringBuffer(luastate, ptr, answer->fqdn_len); + lua_settable(luastate, -3); + + ptr = (uint8_t *)((uint8_t *)answer + sizeof(DNSAnswerEntry) + answer->fqdn_len); + if (answer->type == DNS_RECORD_TYPE_A) { + char a[16] = ""; + PrintInet(AF_INET, (const void *)ptr, a, sizeof(a)); + lua_pushstring(luastate, "addr"); + LuaPushStringBuffer(luastate, (uint8_t *)a, strlen(a)); + lua_settable(luastate, -3); + } else if (answer->type == DNS_RECORD_TYPE_AAAA) { + char a[46]; + PrintInet(AF_INET6, (const void *)ptr, a, sizeof(a)); + lua_pushstring(luastate, "addr"); + LuaPushStringBuffer(luastate, (uint8_t *)a, strlen(a)); + lua_settable(luastate, -3); + } else if (answer->data_len == 0) { + /* not setting 'addr' */ + } else { + lua_pushstring(luastate, "addr"); + LuaPushStringBuffer(luastate, (uint8_t *)ptr, answer->data_len); + lua_settable(luastate, -3); + } + } + + lua_settable(luastate, -3); + } + + return 1; +} + +static int DnsGetAuthorityTable(lua_State *luastate) +{ + if (!(LuaStateNeedProto(luastate, ALPROTO_DNS))) + return LuaCallbackError(luastate, "error: protocol not dns"); + + DNSTransaction *tx = LuaStateGetTX(luastate); + if (tx == NULL) + return LuaCallbackError(luastate, "internal error: no tx"); + + uint32_t u = 0; + lua_newtable(luastate); + DNSAnswerEntry *answer = NULL; + TAILQ_FOREACH(answer, &tx->authority_list, next) { + lua_pushinteger(luastate, u++); + + lua_newtable(luastate); + char record[16] = ""; + DNSCreateTypeString(answer->type, record, sizeof(record)); + lua_pushstring(luastate, "type"); + lua_pushstring(luastate, record); + lua_settable(luastate, -3); + + lua_pushstring(luastate, "ttl"); + lua_pushinteger(luastate, answer->ttl); + lua_settable(luastate, -3); + + { + char *c; + size_t input_len; + c = BytesToString((uint8_t *)((uint8_t *)answer + sizeof(DNSAnswerEntry)), answer->fqdn_len); + if (c != NULL) { + input_len = strlen(c); + /* sanity check */ + if (input_len > (size_t)(2 * answer->fqdn_len)) { + SCFree(c); + return LuaCallbackError(luastate, "invalid length"); + } + lua_pushstring(luastate, "rrname"); + LuaPushStringBuffer(luastate, (uint8_t *)c, input_len); + lua_settable(luastate, -3); + SCFree(c); + } + } + + + lua_settable(luastate, -3); + } + + return 1; +} + + /** \brief register http lua extensions in a luastate */ int LuaRegisterDnsFunctions(lua_State *luastate) { /* registration of the callbacks */ lua_pushcfunction(luastate, DnsGetDnsRrname); lua_setglobal(luastate, "DnsGetDnsRrname"); + + lua_pushcfunction(luastate, DnsGetQueryTable); + lua_setglobal(luastate, "DnsGetQueries"); + + lua_pushcfunction(luastate, DnsGetAnswerTable); + lua_setglobal(luastate, "DnsGetAnswers"); + + lua_pushcfunction(luastate, DnsGetAuthorityTable); + lua_setglobal(luastate, "DnsGetAuthorities"); + + lua_pushcfunction(luastate, DnsGetTxid); + lua_setglobal(luastate, "DnsGetTxid"); + + lua_pushcfunction(luastate, DnsGetRcode); + lua_setglobal(luastate, "DnsGetRcode"); + + lua_pushcfunction(luastate, DnsGetRecursionDesired); + lua_setglobal(luastate, "DnsGetRecursionDesired"); return 0; }