From: Jason Ish Date: Mon, 1 May 2017 23:14:08 +0000 (-0600) Subject: rust: lua support for DNS based Rust X-Git-Tag: suricata-4.0.0-beta1~27 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b588b497793feeb481a02ba2816fee4219fb049b;p=thirdparty%2Fsuricata.git rust: lua support for DNS based Rust Uses Rust wrappers around Lua to populate Lua data structures. --- diff --git a/rust/src/dns/log.rs b/rust/src/dns/log.rs index 3fe4133c84..e2440cc243 100644 --- a/rust/src/dns/log.rs +++ b/rust/src/dns/log.rs @@ -24,7 +24,7 @@ use json::*; use dns::dns::*; use log::*; -fn dns_rrtype_string(rrtype: u16) -> String { +pub fn dns_rrtype_string(rrtype: u16) -> String { match rrtype { DNS_RTYPE_A => "A", DNS_RTYPE_CNAME => "CNAME", @@ -51,7 +51,7 @@ fn dns_rcode_string(flags: u16) -> String { } /// Format bytes as an IP address string. -fn dns_print_addr(addr: &Vec) -> std::string::String { +pub fn dns_print_addr(addr: &Vec) -> std::string::String { if addr.len() == 4 { return format!("{}.{}.{}.{}", addr[0], addr[1], addr[2], addr[3]); } diff --git a/rust/src/dns/lua.rs b/rust/src/dns/lua.rs new file mode 100644 index 0000000000..bcd7a7c402 --- /dev/null +++ b/rust/src/dns/lua.rs @@ -0,0 +1,203 @@ +/* Copyright (C) 2017 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +use std::os::raw::c_int; + +use lua::*; +use dns::dns::*; +use dns::log::*; + +#[no_mangle] +pub extern "C" fn rs_dns_lua_get_tx_id(clua: &mut CLuaState, + tx: &mut DNSTransaction) +{ + let lua = LuaState{ + lua: clua, + }; + + lua.pushinteger(tx.tx_id() as i64); +} + +#[no_mangle] +pub extern "C" fn rs_dns_lua_get_rrname(clua: &mut CLuaState, + tx: &mut DNSTransaction) + -> c_int +{ + let lua = LuaState{ + lua: clua, + }; + + for request in &tx.request { + for query in &request.queries { + lua.pushstring(query.name()); + return 1; + } + } + + for response in &tx.response { + for query in &response.queries { + lua.pushstring(query.name()); + return 1; + } + } + + return 0; +} + +#[no_mangle] +pub extern "C" fn rs_dns_lua_get_query_table(clua: &mut CLuaState, + tx: &mut DNSTransaction) + -> c_int +{ + let lua = LuaState{ + lua: clua, + }; + + let mut i: i64 = 0; + + for request in &tx.request { + + if request.queries.len() == 0 { + break; + } + + lua.newtable(); + + for query in &request.queries { + lua.pushinteger(i); + i += 1; + + lua.newtable(); + + lua.pushstring("type"); + lua.pushstring(&dns_rrtype_string(query.rrtype)); + lua.settable(-3); + + lua.pushstring("rrname"); + lua.pushstring(query.name()); + lua.settable(-3); + + lua.settable(-3); + } + + return 1; + } + + return 0; +} + +#[no_mangle] +pub extern "C" fn rs_dns_lua_get_answer_table(clua: &mut CLuaState, + tx: &mut DNSTransaction) + -> c_int +{ + let lua = LuaState{ + lua: clua, + }; + + let mut i: i64 = 0; + + for response in &tx.response { + + if response.answers.len() == 0 { + break; + } + + lua.newtable(); + + for answer in &response.answers { + lua.pushinteger(i); + i += 1; + + lua.newtable(); + lua.pushstring("type"); + lua.pushstring(&dns_rrtype_string(answer.rrtype)); + lua.settable(-3); + + lua.pushstring("ttl"); + lua.pushinteger(answer.ttl as i64); + lua.settable(-3); + + lua.pushstring("rrname"); + lua.pushstring(answer.name()); + lua.settable(-3); + + if answer.data.len() > 0 { + lua.pushstring("addr"); + match answer.rrtype { + DNS_RTYPE_A | DNS_RTYPE_AAAA => { + lua.pushstring(&dns_print_addr(&answer.data)); + } + _ => { + lua.pushstring(answer.data_to_string()); + } + } + lua.settable(-3); + } + lua.settable(-3); + } + + return 1; + } + + return 0; +} + +#[no_mangle] +pub extern "C" fn rs_dns_lua_get_authority_table(clua: &mut CLuaState, + tx: &mut DNSTransaction) + -> c_int +{ + let lua = LuaState{ + lua: clua, + }; + + let mut i: i64 = 0; + + for response in &tx.response { + + if response.authorities.len() == 0 { + break; + } + + lua.newtable(); + + for answer in &response.authorities { + lua.pushinteger(i); + i += 1; + + lua.newtable(); + lua.pushstring("type"); + lua.pushstring(&dns_rrtype_string(answer.rrtype)); + lua.settable(-3); + + lua.pushstring("ttl"); + lua.pushinteger(answer.ttl as i64); + lua.settable(-3); + + lua.pushstring("rrname"); + lua.pushstring(answer.name()); + lua.settable(-3); + + lua.settable(-3); + } + + return 1; + } + + return 0; +} diff --git a/rust/src/dns/mod.rs b/rust/src/dns/mod.rs index d6693b0a9a..5da27124fb 100644 --- a/rust/src/dns/mod.rs +++ b/rust/src/dns/mod.rs @@ -18,3 +18,6 @@ pub mod parser; pub mod dns; pub mod log; + +#[cfg(feature = "lua")] +pub mod lua; diff --git a/src/util-lua-dns.c b/src/util-lua-dns.c index 761b1f7c9a..c1fe6533c0 100644 --- a/src/util-lua-dns.c +++ b/src/util-lua-dns.c @@ -60,6 +60,7 @@ #ifdef HAVE_RUST #include "rust-dns-dns-gen.h" +#include "rust-dns-lua-gen.h" #endif static int DnsGetDnsRrname(lua_State *luastate) @@ -68,31 +69,10 @@ static int DnsGetDnsRrname(lua_State *luastate) return LuaCallbackError(luastate, "error: protocol not dns"); #ifdef HAVE_RUST RSDNSTransaction *tx = LuaStateGetTX(luastate); - if (tx == NULL) + if (tx == NULL) { return LuaCallbackError(luastate, "internal error: no tx"); - - for (uint16_t i = 0;; i++) { - uint32_t buf_len; - uint8_t *buf; - - if (!rs_dns_tx_get_query_name(tx, i, &buf, &buf_len)) { - break; - } - - char *rrname = BytesToString(buf, buf_len); - if (rrname != NULL) { - size_t input_len = strlen(rrname); - /* sanity check */ - if (input_len > (size_t)(2 * buf_len)) { - SCFree(rrname); - return LuaCallbackError(luastate, "invalid length"); - } - int ret = LuaPushStringBuffer(luastate, (uint8_t *)rrname, - input_len); - SCFree(rrname); - return ret; - } } + return rs_dns_lua_get_rrname(luastate, tx); #else DNSTransaction *tx = LuaStateGetTX(luastate); if (tx == NULL) @@ -126,10 +106,10 @@ static int DnsGetTxid(lua_State *luastate) return LuaCallbackError(luastate, "error: protocol not dns"); #ifdef HAVE_RUST RSDNSTransaction *tx = LuaStateGetTX(luastate); - if (tx == NULL) + if (tx == NULL) { return LuaCallbackError(luastate, "internal error: no tx"); - uint16_t tx_id = rs_dns_tx_get_tx_id(tx); - lua_pushinteger(luastate, tx_id); + } + rs_dns_lua_get_tx_id(luastate, tx); #else DNSTransaction *tx = LuaStateGetTX(luastate); if (tx == NULL) @@ -173,12 +153,11 @@ static int DnsGetRecursionDesired(lua_State *luastate) return LuaCallbackError(luastate, "error: protocol not dns"); #ifdef HAVE_RUST RSDNSTransaction *tx = LuaStateGetTX(luastate); - if (tx == NULL) + if (tx == NULL) { return LuaCallbackError(luastate, "internal error: no tx"); - + } uint16_t flags = rs_dns_tx_get_response_flags(tx); int recursion_desired = flags & 0x0080 ? 1 : 0; - lua_pushboolean(luastate, recursion_desired); #else DNSTransaction *tx = LuaStateGetTX(luastate); @@ -192,59 +171,15 @@ static int DnsGetRecursionDesired(lua_State *luastate) static int DnsGetQueryTable(lua_State *luastate) { -#ifdef HAVE_RUST if (!(LuaStateNeedProto(luastate, ALPROTO_DNS))) return LuaCallbackError(luastate, "error: protocol not dns"); - +#ifdef HAVE_RUST RSDNSTransaction *tx = LuaStateGetTX(luastate); - if (tx == NULL) + if (tx == NULL) { return LuaCallbackError(luastate, "internal error: no tx"); - - lua_newtable(luastate); - - uint8_t *name; - uint32_t name_len; - - for (uint16_t i = 0;; i++) { - - if (!rs_dns_tx_get_query_name(tx, i, &name, &name_len)) { - break; - } - - lua_pushinteger(luastate, i); - lua_newtable(luastate); - - uint16_t rrtype; - if (rs_dns_tx_get_query_rrtype(tx, i, &rrtype)) { - char s_rrtype[16] = ""; - DNSCreateTypeString(rrtype, s_rrtype, sizeof(s_rrtype)); - lua_pushstring(luastate, "type"); - lua_pushstring(luastate, s_rrtype); - lua_settable(luastate, -3); - } - - char *s = BytesToString(name, name_len); - if (s != NULL) { - size_t slen = strlen(s); - if (slen > name_len * 2) { - SCFree(s); - return LuaCallbackError(luastate, "invalid length"); - } - lua_pushstring(luastate, "rrname"); - LuaPushStringBuffer(luastate, (uint8_t *)s, slen); - lua_settable(luastate, -3); - SCFree(s); - } - - lua_pushinteger(luastate, i++); - } - - return 1; + return rs_dns_lua_get_query_table(luastate, tx); #else - 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"); @@ -290,13 +225,12 @@ static int DnsGetQueryTable(lua_State *luastate) static int DnsGetAnswerTable(lua_State *luastate) { -#ifdef HAVE_RUST - SCLogNotice("DnsGetAnswerTable not implemented for Rust DNS."); - return 1; -#else if (!(LuaStateNeedProto(luastate, ALPROTO_DNS))) return LuaCallbackError(luastate, "error: protocol not dns"); - +#ifdef HAVE_RUST + RSDNSTransaction *tx = LuaStateGetTX(luastate); + return rs_dns_lua_get_answer_table(luastate, tx); +#else DNSTransaction *tx = LuaStateGetTX(luastate); if (tx == NULL) return LuaCallbackError(luastate, "internal error: no tx"); @@ -359,13 +293,12 @@ static int DnsGetAnswerTable(lua_State *luastate) static int DnsGetAuthorityTable(lua_State *luastate) { -#ifdef HAVE_RUST - SCLogNotice("DnsGetAuthorityTable not implemented for Rust DNS"); - return 1; -#else if (!(LuaStateNeedProto(luastate, ALPROTO_DNS))) return LuaCallbackError(luastate, "error: protocol not dns"); - +#ifdef HAVE_RUST + RSDNSTransaction *tx = LuaStateGetTX(luastate); + return rs_dns_lua_get_authority_table(luastate, tx); +#else DNSTransaction *tx = LuaStateGetTX(luastate); if (tx == NULL) return LuaCallbackError(luastate, "internal error: no tx");