mirror of
https://github.com/nmap/nmap.git
synced 2025-12-06 04:31:29 +00:00
Update dnssd.lua and related scripts
* Structured output * Fix adding new targets: was adding the multicast address, not the discovered unicast address. * Extract service name and host name from responses * broadcast-dns-service-discovery now lists services under each unicast address instead of under the single multicast/broadcast address.
This commit is contained in:
111
nselib/dnssd.lua
111
nselib/dnssd.lua
@@ -46,6 +46,7 @@ local string = require "string"
|
||||
local stringaux = require "stringaux"
|
||||
local table = require "table"
|
||||
local target = require "target"
|
||||
local outlib = require "outlib"
|
||||
_ENV = stdnse.module("dnssd", stdnse.seeall)
|
||||
|
||||
Util = {
|
||||
@@ -67,8 +68,8 @@ Util = {
|
||||
serviceCompare = function(a, b)
|
||||
-- if no port is found use 999999 for comparing, this way all services
|
||||
-- without ports and device information gets printed at the end
|
||||
local port_a = a.name:match("^(%d+)") or 999999
|
||||
local port_b = b.name:match("^(%d+)") or 999999
|
||||
local port_a = a:match("^(%d+)") or 999999
|
||||
local port_b = b:match("^(%d+)") or 999999
|
||||
|
||||
if ( tonumber(port_a) < tonumber(port_b) ) then
|
||||
return true
|
||||
@@ -210,61 +211,60 @@ Comm = {
|
||||
-- @param response as returned by <code>queryService</code>
|
||||
-- @param result table into which the decoded output should be stored
|
||||
decodeRecords = function( response, result )
|
||||
local service, deviceinfo = {}, {}
|
||||
local service = stdnse.output_table()
|
||||
local txt = {}
|
||||
local ipv6, srv, address, port, proto
|
||||
|
||||
local record = ( #response.questions > 0 and response.questions[1].dname ) and response.questions[1].dname or ""
|
||||
|
||||
local status, ip = Comm.getRecordType( dns.types.A, response, false )
|
||||
if status then address = ip end
|
||||
local status, ipv4 = Comm.getRecordType( dns.types.A, response, false )
|
||||
if status then service.ipv4 = ipv4 end
|
||||
|
||||
status, ipv6 = Comm.getRecordType( dns.types.AAAA, response, false )
|
||||
if status then
|
||||
address = address or ""
|
||||
address = address .. " " .. ipv6
|
||||
end
|
||||
local status, ipv6 = Comm.getRecordType( dns.types.AAAA, response, false )
|
||||
if status then service.ipv6 = ipv6 end
|
||||
|
||||
status, txt = Comm.getRecordType( dns.types.TXT, response, true )
|
||||
local status, name = Comm.getRecordType( dns.types.PTR, response, false )
|
||||
if status then
|
||||
for _, v in ipairs(txt) do
|
||||
if v:len() > 0 then
|
||||
table.insert(service, v)
|
||||
end
|
||||
local i = name:find("." .. record, 1, true)
|
||||
if i then
|
||||
name = name:sub(1, i - 1)
|
||||
end
|
||||
service.name = name
|
||||
end
|
||||
|
||||
status, srv = Comm.getRecordType( dns.types.SRV, response, false )
|
||||
local name, port
|
||||
local status, srv = Comm.getRecordType( dns.types.SRV, response, false )
|
||||
if status then
|
||||
local srvparams = stringaux.strsplit( ":", srv )
|
||||
|
||||
if #srvparams > 3 then
|
||||
name = srvparams[4]:gsub("%.local$", "")
|
||||
port = srvparams[3]
|
||||
if service.name ~= name then
|
||||
service.hostname = name
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if address then
|
||||
table.insert( service, ("Address=%s"):format( address ) )
|
||||
status, txt = Comm.getRecordType( dns.types.TXT, response, true )
|
||||
if status then
|
||||
for _, t in ipairs(txt) do
|
||||
if #t > 0 then
|
||||
service.TXT = txt
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if record == "_device-info._tcp.local" then
|
||||
service.name = "Device Information"
|
||||
deviceinfo = service
|
||||
table.insert(result, deviceinfo)
|
||||
result["Device Information"] = service
|
||||
else
|
||||
local serviceparams = stringaux.strsplit("[.]", record)
|
||||
|
||||
if #serviceparams > 2 then
|
||||
local servicename = serviceparams[1]:sub(2)
|
||||
local proto = serviceparams[2]:sub(2)
|
||||
|
||||
if port == nil or proto == nil or servicename == nil then
|
||||
service.name = record
|
||||
else
|
||||
service.name = string.format( "%s/%s %s", port, proto, servicename)
|
||||
end
|
||||
local heading
|
||||
local servicename, proto = record:match("^_([^.]+)%._([^.]+)%.")
|
||||
if port and servicename then
|
||||
heading = string.format( "%s/%s %s", port, proto, servicename)
|
||||
else
|
||||
heading = record
|
||||
end
|
||||
table.insert( result, service )
|
||||
result[heading] = service
|
||||
end
|
||||
end,
|
||||
|
||||
@@ -360,36 +360,41 @@ Helper = {
|
||||
-- Wait for all threads to finish running
|
||||
while Util.threadCount(threads)>0 do condvar("wait") end
|
||||
|
||||
local ipsvctbl = {}
|
||||
if ( mcast ) then
|
||||
-- Process all records that were returned
|
||||
local addr1, addr2
|
||||
if nmap.address_family() == "inet" then
|
||||
addr1 = "ipv4"
|
||||
addr2 = "ipv6"
|
||||
else
|
||||
addr1 = "ipv6"
|
||||
addr2 = "ipv4"
|
||||
end
|
||||
local ipsvctbl = {}
|
||||
for svcname, response in pairs(svcresponse) do
|
||||
for _, r in ipairs( response ) do
|
||||
ipsvctbl[r.peer] = ipsvctbl[r.peer] or {}
|
||||
Comm.decodeRecords( r.output, ipsvctbl[r.peer] )
|
||||
local key = r[addr1]
|
||||
if key then
|
||||
target.add(key)
|
||||
else
|
||||
key = r[addr2] or r.peer
|
||||
end
|
||||
ipsvctbl[key] = ipsvctbl[key] or {}
|
||||
Comm.decodeRecords( r.output, ipsvctbl[key] )
|
||||
end
|
||||
end
|
||||
for k, svc in pairs(ipsvctbl) do
|
||||
ipsvctbl[k] = outlib.sorted_by_key(svc, Util.serviceCompare)
|
||||
end
|
||||
return true, outlib.sorted_by_key(ipsvctbl, Util.ipCompare)
|
||||
else
|
||||
-- Process all records that were returned
|
||||
for svcname, response in pairs(svcresponse) do
|
||||
Comm.decodeRecords( response, result )
|
||||
end
|
||||
return true, outlib.sorted_by_key(result, Util.serviceCompare)
|
||||
end
|
||||
|
||||
if ( mcast ) then
|
||||
-- Restructure and build our output table
|
||||
for ip, svctbl in pairs( ipsvctbl ) do
|
||||
table.sort(svctbl, Util.serviceCompare)
|
||||
svctbl.name = ip
|
||||
if target.ALLOW_NEW_TARGETS then target.add(ip) end
|
||||
table.insert( result, svctbl )
|
||||
end
|
||||
table.sort( result, Util.ipCompare )
|
||||
else
|
||||
-- sort the tables per port
|
||||
table.sort( result, Util.serviceCompare )
|
||||
end
|
||||
return true, result
|
||||
return false
|
||||
end,
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
local dnssd = require "dnssd"
|
||||
local stdnse = require "stdnse"
|
||||
local oops = require "oops"
|
||||
|
||||
description=[[
|
||||
Attempts to discover hosts' services using the DNS Service Discovery protocol. It sends a multicast DNS-SD query and collects all the responses.
|
||||
@@ -50,8 +51,5 @@ action = function()
|
||||
local helper = dnssd.Helper:new( )
|
||||
helper:setMulticast(true)
|
||||
|
||||
local status, result = helper:queryServices()
|
||||
if ( status ) then
|
||||
return stdnse.format_output(true, result)
|
||||
end
|
||||
oops.output(helper:queryServices())
|
||||
end
|
||||
|
||||
@@ -61,7 +61,7 @@ action = function(host, port)
|
||||
if ( status ) then
|
||||
-- set port to open
|
||||
nmap.set_port_state(host, port, "open")
|
||||
return stdnse.format_output(true, result)
|
||||
return result
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user