mirror of
https://github.com/nmap/nmap.git
synced 2025-12-30 11:29:01 +00:00
Final re-indent for scripts.
This commit is contained in:
@@ -52,142 +52,142 @@ local QTYPE_NODEADDRESSES = 3
|
||||
local QTYPE_NODEIPV4ADDRESSES = 4
|
||||
|
||||
local QTYPE_STRINGS = {
|
||||
[QTYPE_NOOP] = "NOOP",
|
||||
[QTYPE_NODENAME] = "Hostnames",
|
||||
[QTYPE_NODEADDRESSES] = "IPv6 addresses",
|
||||
[QTYPE_NODEIPV4ADDRESSES] = "IPv4 addresses",
|
||||
[QTYPE_NOOP] = "NOOP",
|
||||
[QTYPE_NODENAME] = "Hostnames",
|
||||
[QTYPE_NODEADDRESSES] = "IPv6 addresses",
|
||||
[QTYPE_NODEIPV4ADDRESSES] = "IPv4 addresses",
|
||||
}
|
||||
|
||||
local function build_ni_query(src, dst, qtype)
|
||||
local payload, p, flags
|
||||
local nonce
|
||||
local payload, p, flags
|
||||
local nonce
|
||||
|
||||
nonce = openssl.rand_pseudo_bytes(8)
|
||||
if qtype == QTYPE_NODENAME then
|
||||
flags = 0x0000
|
||||
elseif qtype == QTYPE_NODEADDRESSES then
|
||||
-- Set all the flags GSLCA (see RFC 4620, Figure 3).
|
||||
flags = 0x003E
|
||||
elseif qtype == QTYPE_NODEIPV4ADDRESSES then
|
||||
-- Set the A flag (see RFC 4620, Figure 4).
|
||||
flags = 0x0002
|
||||
else
|
||||
error("Unknown qtype " .. qtype)
|
||||
end
|
||||
payload = bin.pack(">SSAA", qtype, flags, nonce, dst)
|
||||
p = packet.Packet:new()
|
||||
p:build_icmpv6_header(ICMPv6_NODEINFOQUERY, ICMPv6_NODEINFOQUERY_IPv6ADDR, payload, src, dst)
|
||||
p:build_ipv6_packet(src, dst, packet.IPPROTO_ICMPV6)
|
||||
nonce = openssl.rand_pseudo_bytes(8)
|
||||
if qtype == QTYPE_NODENAME then
|
||||
flags = 0x0000
|
||||
elseif qtype == QTYPE_NODEADDRESSES then
|
||||
-- Set all the flags GSLCA (see RFC 4620, Figure 3).
|
||||
flags = 0x003E
|
||||
elseif qtype == QTYPE_NODEIPV4ADDRESSES then
|
||||
-- Set the A flag (see RFC 4620, Figure 4).
|
||||
flags = 0x0002
|
||||
else
|
||||
error("Unknown qtype " .. qtype)
|
||||
end
|
||||
payload = bin.pack(">SSAA", qtype, flags, nonce, dst)
|
||||
p = packet.Packet:new()
|
||||
p:build_icmpv6_header(ICMPv6_NODEINFOQUERY, ICMPv6_NODEINFOQUERY_IPv6ADDR, payload, src, dst)
|
||||
p:build_ipv6_packet(src, dst, packet.IPPROTO_ICMPV6)
|
||||
|
||||
return p.buf
|
||||
return p.buf
|
||||
end
|
||||
|
||||
function hostrule(host)
|
||||
return nmap.is_privileged() and #host.bin_ip == 16 and host.interface
|
||||
return nmap.is_privileged() and #host.bin_ip == 16 and host.interface
|
||||
end
|
||||
|
||||
local function open_sniffer(host)
|
||||
local bpf
|
||||
local s
|
||||
local bpf
|
||||
local s
|
||||
|
||||
s = nmap.new_socket()
|
||||
bpf = string.format("ip6 and src host %s", host.ip)
|
||||
s:pcap_open(host.interface, 1500, false, bpf)
|
||||
s = nmap.new_socket()
|
||||
bpf = string.format("ip6 and src host %s", host.ip)
|
||||
s:pcap_open(host.interface, 1500, false, bpf)
|
||||
|
||||
return s
|
||||
return s
|
||||
end
|
||||
|
||||
local function send_queries(host)
|
||||
local dnet
|
||||
local dnet
|
||||
|
||||
dnet = nmap.new_dnet()
|
||||
dnet:ip_open()
|
||||
local p = build_ni_query(host.bin_ip_src, host.bin_ip, QTYPE_NODEADDRESSES)
|
||||
dnet:ip_send(p, host)
|
||||
p = build_ni_query(host.bin_ip_src, host.bin_ip, QTYPE_NODENAME)
|
||||
dnet:ip_send(p, host)
|
||||
p = build_ni_query(host.bin_ip_src, host.bin_ip, QTYPE_NODEIPV4ADDRESSES)
|
||||
dnet:ip_send(p, host)
|
||||
dnet:ip_close()
|
||||
dnet = nmap.new_dnet()
|
||||
dnet:ip_open()
|
||||
local p = build_ni_query(host.bin_ip_src, host.bin_ip, QTYPE_NODEADDRESSES)
|
||||
dnet:ip_send(p, host)
|
||||
p = build_ni_query(host.bin_ip_src, host.bin_ip, QTYPE_NODENAME)
|
||||
dnet:ip_send(p, host)
|
||||
p = build_ni_query(host.bin_ip_src, host.bin_ip, QTYPE_NODEIPV4ADDRESSES)
|
||||
dnet:ip_send(p, host)
|
||||
dnet:ip_close()
|
||||
end
|
||||
|
||||
local function empty(t)
|
||||
return not next(t)
|
||||
return not next(t)
|
||||
end
|
||||
|
||||
-- Try to decode a Node Name reply data field. If successful, returns true and
|
||||
-- a list of DNS names. In case of a parsing error, returns false and the
|
||||
-- partial list of names that were parsed prior to the error.
|
||||
local function try_decode_nodenames(data)
|
||||
local ttl
|
||||
local names = {}
|
||||
local pos = nil
|
||||
local ttl
|
||||
local names = {}
|
||||
local pos = nil
|
||||
|
||||
pos, ttl = bin.unpack(">I", data, pos)
|
||||
if not ttl then
|
||||
return false, names
|
||||
end
|
||||
while pos <= #data do
|
||||
local name
|
||||
pos, ttl = bin.unpack(">I", data, pos)
|
||||
if not ttl then
|
||||
return false, names
|
||||
end
|
||||
while pos <= #data do
|
||||
local name
|
||||
|
||||
pos, name = dns.decStr(data, pos)
|
||||
if not name then
|
||||
return false, names
|
||||
end
|
||||
-- Ignore empty names, such as those at the end.
|
||||
if name ~= "" then
|
||||
names[#names + 1] = name
|
||||
end
|
||||
end
|
||||
pos, name = dns.decStr(data, pos)
|
||||
if not name then
|
||||
return false, names
|
||||
end
|
||||
-- Ignore empty names, such as those at the end.
|
||||
if name ~= "" then
|
||||
names[#names + 1] = name
|
||||
end
|
||||
end
|
||||
|
||||
return true, names
|
||||
return true, names
|
||||
end
|
||||
|
||||
local function stringify_noop(flags, data)
|
||||
return "replied"
|
||||
return "replied"
|
||||
end
|
||||
|
||||
-- RFC 4620, section 6.3.
|
||||
local function stringify_nodename(flags, data)
|
||||
local status, names
|
||||
local text
|
||||
local status, names
|
||||
local text
|
||||
|
||||
status, names = try_decode_nodenames(data)
|
||||
if empty(names) then
|
||||
return
|
||||
end
|
||||
text = stdnse.strjoin(", ", names)
|
||||
if not status then
|
||||
text = text .. " (parsing error)"
|
||||
end
|
||||
status, names = try_decode_nodenames(data)
|
||||
if empty(names) then
|
||||
return
|
||||
end
|
||||
text = stdnse.strjoin(", ", names)
|
||||
if not status then
|
||||
text = text .. " (parsing error)"
|
||||
end
|
||||
|
||||
return text
|
||||
return text
|
||||
end
|
||||
|
||||
-- RFC 4620, section 6.3.
|
||||
local function stringify_nodeaddresses(flags, data)
|
||||
local ttl, binaddr
|
||||
local text
|
||||
local addrs = {}
|
||||
local pos = nil
|
||||
local ttl, binaddr
|
||||
local text
|
||||
local addrs = {}
|
||||
local pos = nil
|
||||
|
||||
while true do
|
||||
pos, ttl, binaddr = bin.unpack(">IA16", data, pos)
|
||||
if not ttl then
|
||||
break
|
||||
end
|
||||
addrs[#addrs + 1] = packet.toipv6(binaddr)
|
||||
end
|
||||
if empty(addrs) then
|
||||
return
|
||||
end
|
||||
while true do
|
||||
pos, ttl, binaddr = bin.unpack(">IA16", data, pos)
|
||||
if not ttl then
|
||||
break
|
||||
end
|
||||
addrs[#addrs + 1] = packet.toipv6(binaddr)
|
||||
end
|
||||
if empty(addrs) then
|
||||
return
|
||||
end
|
||||
|
||||
text = stdnse.strjoin(", ", addrs)
|
||||
if bit.band(flags, 0x01) ~= 0 then
|
||||
text = text .. " (more omitted for space reasons)"
|
||||
end
|
||||
text = stdnse.strjoin(", ", addrs)
|
||||
if bit.band(flags, 0x01) ~= 0 then
|
||||
text = text .. " (more omitted for space reasons)"
|
||||
end
|
||||
|
||||
return text
|
||||
return text
|
||||
end
|
||||
|
||||
-- RFC 4620, section 6.4.
|
||||
@@ -200,133 +200,133 @@ end
|
||||
-- 00 00 00 00 0e 6d 61 63 2d 6d 69 6e 69 2e 6c 6f .....mac -mini.lo
|
||||
-- 63 61 6c cal
|
||||
local function stringify_nodeipv4addresses(flags, data)
|
||||
local status, names
|
||||
local ttl, binaddr
|
||||
local text
|
||||
local addrs = {}
|
||||
local pos = nil
|
||||
local status, names
|
||||
local ttl, binaddr
|
||||
local text
|
||||
local addrs = {}
|
||||
local pos = nil
|
||||
|
||||
-- Check for DNS names.
|
||||
status, names = try_decode_nodenames(data .. "\0\0")
|
||||
if status then
|
||||
return "(actually hostnames) " .. stdnse.strjoin(", ", names)
|
||||
end
|
||||
-- Check for DNS names.
|
||||
status, names = try_decode_nodenames(data .. "\0\0")
|
||||
if status then
|
||||
return "(actually hostnames) " .. stdnse.strjoin(", ", names)
|
||||
end
|
||||
|
||||
-- Okay, looks like it's really IP addresses.
|
||||
while true do
|
||||
pos, ttl, binaddr = bin.unpack(">IA4", data, pos)
|
||||
if not ttl then
|
||||
break
|
||||
end
|
||||
addrs[#addrs + 1] = packet.toip(binaddr)
|
||||
end
|
||||
if empty(addrs) then
|
||||
return
|
||||
end
|
||||
-- Okay, looks like it's really IP addresses.
|
||||
while true do
|
||||
pos, ttl, binaddr = bin.unpack(">IA4", data, pos)
|
||||
if not ttl then
|
||||
break
|
||||
end
|
||||
addrs[#addrs + 1] = packet.toip(binaddr)
|
||||
end
|
||||
if empty(addrs) then
|
||||
return
|
||||
end
|
||||
|
||||
text = stdnse.strjoin(", ", addrs)
|
||||
if bit.band(flags, 0x01) ~= 0 then
|
||||
text = text .. " (more omitted for space reasons)"
|
||||
end
|
||||
text = stdnse.strjoin(", ", addrs)
|
||||
if bit.band(flags, 0x01) ~= 0 then
|
||||
text = text .. " (more omitted for space reasons)"
|
||||
end
|
||||
|
||||
return text
|
||||
return text
|
||||
end
|
||||
|
||||
local STRINGIFY = {
|
||||
[QTYPE_NOOP] = stringify_noop,
|
||||
[QTYPE_NODENAME] = stringify_nodename,
|
||||
[QTYPE_NODEADDRESSES] = stringify_nodeaddresses,
|
||||
[QTYPE_NODEIPV4ADDRESSES] = stringify_nodeipv4addresses,
|
||||
[QTYPE_NOOP] = stringify_noop,
|
||||
[QTYPE_NODENAME] = stringify_nodename,
|
||||
[QTYPE_NODEADDRESSES] = stringify_nodeaddresses,
|
||||
[QTYPE_NODEIPV4ADDRESSES] = stringify_nodeipv4addresses,
|
||||
}
|
||||
|
||||
local function handle_received_packet(buf)
|
||||
local p, qtype, flags, data
|
||||
local text
|
||||
local p, qtype, flags, data
|
||||
local text
|
||||
|
||||
p = packet.Packet:new(buf)
|
||||
if p.icmpv6_type ~= ICMPv6_NODEINFORESP then
|
||||
return
|
||||
end
|
||||
qtype = packet.u16(p.buf, p.icmpv6_offset + 4)
|
||||
flags = packet.u16(p.buf, p.icmpv6_offset + 6)
|
||||
data = string.sub(p.buf, p.icmpv6_offset + 16 + 1)
|
||||
p = packet.Packet:new(buf)
|
||||
if p.icmpv6_type ~= ICMPv6_NODEINFORESP then
|
||||
return
|
||||
end
|
||||
qtype = packet.u16(p.buf, p.icmpv6_offset + 4)
|
||||
flags = packet.u16(p.buf, p.icmpv6_offset + 6)
|
||||
data = string.sub(p.buf, p.icmpv6_offset + 16 + 1)
|
||||
|
||||
if not STRINGIFY[qtype] then
|
||||
-- This is a not a qtype we sent or know about.
|
||||
stdnse.print_debug(1, "Got NI reply with unknown qtype %d from %s", qtype, p.ip6_src)
|
||||
return
|
||||
end
|
||||
if not STRINGIFY[qtype] then
|
||||
-- This is a not a qtype we sent or know about.
|
||||
stdnse.print_debug(1, "Got NI reply with unknown qtype %d from %s", qtype, p.ip6_src)
|
||||
return
|
||||
end
|
||||
|
||||
if p.icmpv6_code == ICMPv6_NODEINFORESP_SUCCESS then
|
||||
text = STRINGIFY[qtype](flags, data)
|
||||
elseif p.icmpv6_code == ICMPv6_NODEINFORESP_REFUSED then
|
||||
text = "refused"
|
||||
elseif p.icmpv6_code == ICMPv6_NODEINFORESP_UNKNOWN then
|
||||
text = string.format("target said: qtype %d is unknown", qtype)
|
||||
else
|
||||
text = string.format("unknown ICMPv6 code %d for qtype %d", p.icmpv6_code, qtype)
|
||||
end
|
||||
if p.icmpv6_code == ICMPv6_NODEINFORESP_SUCCESS then
|
||||
text = STRINGIFY[qtype](flags, data)
|
||||
elseif p.icmpv6_code == ICMPv6_NODEINFORESP_REFUSED then
|
||||
text = "refused"
|
||||
elseif p.icmpv6_code == ICMPv6_NODEINFORESP_UNKNOWN then
|
||||
text = string.format("target said: qtype %d is unknown", qtype)
|
||||
else
|
||||
text = string.format("unknown ICMPv6 code %d for qtype %d", p.icmpv6_code, qtype)
|
||||
end
|
||||
|
||||
return qtype, text
|
||||
return qtype, text
|
||||
end
|
||||
|
||||
local function format_results(results)
|
||||
local QTYPE_ORDER = {
|
||||
QTYPE_NOOP,
|
||||
QTYPE_NODENAME,
|
||||
QTYPE_NODEADDRESSES,
|
||||
QTYPE_NODEIPV4ADDRESSES,
|
||||
}
|
||||
local output
|
||||
local QTYPE_ORDER = {
|
||||
QTYPE_NOOP,
|
||||
QTYPE_NODENAME,
|
||||
QTYPE_NODEADDRESSES,
|
||||
QTYPE_NODEIPV4ADDRESSES,
|
||||
}
|
||||
local output
|
||||
|
||||
output = {}
|
||||
for _, qtype in ipairs(QTYPE_ORDER) do
|
||||
if results[qtype] then
|
||||
output[#output + 1] = QTYPE_STRINGS[qtype] .. ": " .. results[qtype]
|
||||
end
|
||||
end
|
||||
output = {}
|
||||
for _, qtype in ipairs(QTYPE_ORDER) do
|
||||
if results[qtype] then
|
||||
output[#output + 1] = QTYPE_STRINGS[qtype] .. ": " .. results[qtype]
|
||||
end
|
||||
end
|
||||
|
||||
return stdnse.format_output(true, output)
|
||||
return stdnse.format_output(true, output)
|
||||
end
|
||||
|
||||
function action(host)
|
||||
local s
|
||||
local timeout, end_time, now
|
||||
local pending, results
|
||||
local s
|
||||
local timeout, end_time, now
|
||||
local pending, results
|
||||
|
||||
timeout = host.times.timeout * 10
|
||||
timeout = host.times.timeout * 10
|
||||
|
||||
s = open_sniffer(host)
|
||||
s = open_sniffer(host)
|
||||
|
||||
send_queries(host)
|
||||
send_queries(host)
|
||||
|
||||
pending = {
|
||||
[QTYPE_NODENAME] = true,
|
||||
[QTYPE_NODEADDRESSES] = true,
|
||||
[QTYPE_NODEIPV4ADDRESSES] = true,
|
||||
}
|
||||
results = {}
|
||||
pending = {
|
||||
[QTYPE_NODENAME] = true,
|
||||
[QTYPE_NODEADDRESSES] = true,
|
||||
[QTYPE_NODEIPV4ADDRESSES] = true,
|
||||
}
|
||||
results = {}
|
||||
|
||||
now = nmap.clock_ms()
|
||||
end_time = now + timeout
|
||||
repeat
|
||||
local _, status, buf
|
||||
now = nmap.clock_ms()
|
||||
end_time = now + timeout
|
||||
repeat
|
||||
local _, status, buf
|
||||
|
||||
s:set_timeout((end_time - now) * 1000)
|
||||
s:set_timeout((end_time - now) * 1000)
|
||||
|
||||
status, _, _, buf = s:pcap_receive()
|
||||
if status then
|
||||
local qtype, text = handle_received_packet(buf)
|
||||
if qtype then
|
||||
results[qtype] = text
|
||||
pending[qtype] = nil
|
||||
end
|
||||
end
|
||||
status, _, _, buf = s:pcap_receive()
|
||||
if status then
|
||||
local qtype, text = handle_received_packet(buf)
|
||||
if qtype then
|
||||
results[qtype] = text
|
||||
pending[qtype] = nil
|
||||
end
|
||||
end
|
||||
|
||||
now = nmap.clock_ms()
|
||||
until empty(pending) or now > end_time
|
||||
now = nmap.clock_ms()
|
||||
until empty(pending) or now > end_time
|
||||
|
||||
s:pcap_close()
|
||||
s:pcap_close()
|
||||
|
||||
return format_results(results)
|
||||
return format_results(results)
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user