mirror of
https://github.com/nmap/nmap.git
synced 2025-12-22 23:49:03 +00:00
o [NSE] Added ipv6 support to the wsdd, dnssd and upnp libraries. Applied
patch from Dan Miller that fixes errors in processing and sorting ipv6 addresses in scripts using these libraries. [Daniel Miller, Patrik]
This commit is contained in:
@@ -1,5 +1,9 @@
|
|||||||
# Nmap Changelog ($Id$); -*-text-*-
|
# Nmap Changelog ($Id$); -*-text-*-
|
||||||
|
|
||||||
|
o [NSE] Added ipv6 support to the wsdd, dnssd and upnp libraries. Applied
|
||||||
|
patch from Dan Miller that fixes errors in processing and sorting ipv6
|
||||||
|
addresses in scripts using these libraries. [Daniel Miller, Patrik]
|
||||||
|
|
||||||
o [NSE] Added minimal Service Location Protocol (SLP) library and the script
|
o [NSE] Added minimal Service Location Protocol (SLP) library and the script
|
||||||
broadcast-novell-locate that detects servers running eDirectory. [Patrik]
|
broadcast-novell-locate that detects servers running eDirectory. [Patrik]
|
||||||
|
|
||||||
|
|||||||
@@ -41,31 +41,17 @@ module(... or "dnssd", package.seeall)
|
|||||||
|
|
||||||
require 'dns'
|
require 'dns'
|
||||||
require 'target'
|
require 'target'
|
||||||
|
require 'ipOps'
|
||||||
|
|
||||||
Util = {
|
Util = {
|
||||||
|
|
||||||
--- Converts a string ip to a numeric value suitable for comparing
|
|
||||||
--
|
|
||||||
-- @param ip string containing the ip to convert
|
|
||||||
-- @return number containing the converted ip
|
|
||||||
ipToNumber = function(ip)
|
|
||||||
local o1, o2, o3, o4 = ip:match("^(%d*)%.(%d*)%.(%d*)%.(%d*)$")
|
|
||||||
return (256^3) * o1 + (256^2) * o2 + (256^1) * o3 + (256^0) * o4
|
|
||||||
end,
|
|
||||||
|
|
||||||
--- Compare function used for sorting IP-addresses
|
--- Compare function used for sorting IP-addresses
|
||||||
--
|
--
|
||||||
-- @param a table containing first item
|
-- @param a table containing first item
|
||||||
-- @param b table containing second item
|
-- @param b table containing second item
|
||||||
-- @return true if the port of a is less than the port of b
|
-- @return true if a is less than b
|
||||||
ipCompare = function(a, b)
|
ipCompare = function(a, b)
|
||||||
local ip_a = Util.ipToNumber(a.name) or 0
|
return ipOps.compare_ip(a, "lt", b)
|
||||||
local ip_b = Util.ipToNumber(b.name) or 0
|
|
||||||
|
|
||||||
if ( tonumber(ip_a) < tonumber(ip_b) ) then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end,
|
end,
|
||||||
|
|
||||||
--- Function used to compare discovered DNS services so they can be sorted
|
--- Function used to compare discovered DNS services so they can be sorted
|
||||||
@@ -229,7 +215,10 @@ Comm = {
|
|||||||
if status then address = ip end
|
if status then address = ip end
|
||||||
|
|
||||||
status, ipv6 = Comm.getRecordType( dns.types.AAAA, response, false )
|
status, ipv6 = Comm.getRecordType( dns.types.AAAA, response, false )
|
||||||
if status then address = address .. " " .. ipv6 end
|
if status then
|
||||||
|
address = address or ""
|
||||||
|
address = address .. " " .. ipv6
|
||||||
|
end
|
||||||
|
|
||||||
status, txt = Comm.getRecordType( dns.types.TXT, response, true )
|
status, txt = Comm.getRecordType( dns.types.TXT, response, true )
|
||||||
if status then
|
if status then
|
||||||
@@ -337,7 +326,8 @@ Helper = {
|
|||||||
local status, response
|
local status, response
|
||||||
local mcast = self.mcast
|
local mcast = self.mcast
|
||||||
local port = self.port or 5353
|
local port = self.port or 5353
|
||||||
local host = mcast and "224.0.0.251" or self.host
|
local family = nmap.address_family()
|
||||||
|
local host = mcast and (family=="inet6" and "ff02::fb" or "224.0.0.251") or self.host
|
||||||
local service = service or stdnse.get_script_args('dnssd.services')
|
local service = service or stdnse.get_script_args('dnssd.services')
|
||||||
|
|
||||||
if ( not(service) ) then
|
if ( not(service) ) then
|
||||||
|
|||||||
110
nselib/ipOps.lua
110
nselib/ipOps.lua
@@ -11,6 +11,7 @@ local tonumber = tonumber
|
|||||||
|
|
||||||
local stdnse = require "stdnse"
|
local stdnse = require "stdnse"
|
||||||
local bit = require "bit"
|
local bit = require "bit"
|
||||||
|
local bin = require "bin"
|
||||||
|
|
||||||
module ( "ipOps" )
|
module ( "ipOps" )
|
||||||
|
|
||||||
@@ -126,7 +127,7 @@ end
|
|||||||
--
|
--
|
||||||
-- Note: IPv6 addresses are not supported. Currently, numbers in NSE are
|
-- Note: IPv6 addresses are not supported. Currently, numbers in NSE are
|
||||||
-- limited to 10^14, and consequently not all IPv6 addresses can be
|
-- limited to 10^14, and consequently not all IPv6 addresses can be
|
||||||
-- represented.
|
-- represented. Consider using <code>ip_to_str</code> for IPv6 addresses.
|
||||||
-- @param ip String representing an IPv4 address. Shortened notation is
|
-- @param ip String representing an IPv4 address. Shortened notation is
|
||||||
-- permitted.
|
-- permitted.
|
||||||
-- @usage
|
-- @usage
|
||||||
@@ -211,7 +212,8 @@ end
|
|||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
-- Compares two IP addresses (from the same address family).
|
-- Compares two IP addresses. When comparing addresses from different families,
|
||||||
|
-- IPv4 addresses will sort before IPv6 addresses.
|
||||||
-- @param left String representing an IPv4 or IPv6 address. Shortened
|
-- @param left String representing an IPv4 or IPv6 address. Shortened
|
||||||
-- notation is permitted.
|
-- notation is permitted.
|
||||||
-- @param op A comparison operator which may be one of the following
|
-- @param op A comparison operator which may be one of the following
|
||||||
@@ -231,47 +233,36 @@ compare_ip = function( left, op, right )
|
|||||||
return nil, "Error in ipOps.compare_ip: Expected IP address as a string."
|
return nil, "Error in ipOps.compare_ip: Expected IP address as a string."
|
||||||
end
|
end
|
||||||
|
|
||||||
if ( left:match( ":" ) and not right:match( ":" ) ) or ( not left:match( ":" ) and right:match( ":" ) ) then
|
|
||||||
return nil, "Error in ipOps.compare_ip: IP addresses must be from the same address family."
|
|
||||||
end
|
|
||||||
|
|
||||||
if op == "lt" or op == "le" then
|
|
||||||
left, right = right, left
|
|
||||||
elseif op ~= "eq" and op ~= "ge" and op ~= "gt" then
|
|
||||||
return nil, "Error in ipOps.compare_ip: Invalid Operator."
|
|
||||||
end
|
|
||||||
|
|
||||||
local err ={}
|
local err ={}
|
||||||
left, err[#err+1] = ip_to_bin( left )
|
left, err[#err+1] = ip_to_str( left )
|
||||||
right, err[#err+1] = ip_to_bin( right )
|
right, err[#err+1] = ip_to_str( right )
|
||||||
if #err > 0 then
|
if #err > 0 then
|
||||||
return nil, table.concat( err, " " )
|
return nil, table.concat( err, " " )
|
||||||
end
|
end
|
||||||
|
|
||||||
if # left ~= # right then
|
if #left > #right then
|
||||||
-- shouldn't happen...
|
left = bin.pack( "CA", 0x06, left )
|
||||||
return nil, "Error in ipOps.compare_ip: Binary IP addresses were of different lengths."
|
right = bin.pack( "CA", 0x04, right )
|
||||||
|
elseif #right > #left then
|
||||||
|
right = bin.pack( "CA", 0x06, right )
|
||||||
|
left = bin.pack( "CA", 0x04, left )
|
||||||
end
|
end
|
||||||
|
|
||||||
-- equal?
|
if ( op == "eq" ) then
|
||||||
if ( op == "eq" or op == "le" or op == "ge" ) and left == right then
|
return ( left == right )
|
||||||
return true
|
elseif ( op == "ne" ) then
|
||||||
elseif op == "eq" then
|
return ( left ~= right )
|
||||||
return false
|
elseif ( op == "le" ) then
|
||||||
|
return ( left <= right )
|
||||||
|
elseif ( op == "ge" ) then
|
||||||
|
return ( left >= right )
|
||||||
|
elseif ( op == "lt" ) then
|
||||||
|
return ( left < right )
|
||||||
|
elseif ( op == "gt" ) then
|
||||||
|
return ( left > right )
|
||||||
end
|
end
|
||||||
|
|
||||||
-- starting from the leftmost bit, subtract the bit in right from the bit in left
|
return nil, "Error in ipOps.compare_ip: Invalid Operator."
|
||||||
local compare
|
|
||||||
for i = 1, # left , 1 do
|
|
||||||
compare = tonumber( string.sub( left, i, i ) ) - tonumber( string.sub( right, i, i ) )
|
|
||||||
if compare == 1 then
|
|
||||||
return true
|
|
||||||
elseif compare == -1 then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -327,12 +318,15 @@ end
|
|||||||
-- the IPv4 portion is shortened and does not contain a dot, in which case the
|
-- the IPv4 portion is shortened and does not contain a dot, in which case the
|
||||||
-- address will be treated as IPv6.
|
-- address will be treated as IPv6.
|
||||||
-- @param ip String representing an IPv4 or IPv6 address in shortened or full notation.
|
-- @param ip String representing an IPv4 or IPv6 address in shortened or full notation.
|
||||||
|
-- @param family String representing the address family to expand to. Only
|
||||||
|
-- affects IPv4 addresses when "inet6" is provided, causing the function to
|
||||||
|
-- return an IPv4-mapped IPv6 address.
|
||||||
-- @usage
|
-- @usage
|
||||||
-- local ip = ipOps.expand_ip( "2001::" )
|
-- local ip = ipOps.expand_ip( "2001::" )
|
||||||
-- @return String representing a fully expanded IPv4 or IPv6 address (or
|
-- @return String representing a fully expanded IPv4 or IPv6 address (or
|
||||||
-- <code>nil</code> in case of an error).
|
-- <code>nil</code> in case of an error).
|
||||||
-- @return String error message in case of an error.
|
-- @return String error message in case of an error.
|
||||||
expand_ip = function( ip )
|
expand_ip = function( ip, family )
|
||||||
local err
|
local err
|
||||||
|
|
||||||
if type( ip ) ~= "string" or ip == "" then
|
if type( ip ) ~= "string" or ip == "" then
|
||||||
@@ -355,7 +349,18 @@ expand_ip = function( ip )
|
|||||||
while #octets < 4 do
|
while #octets < 4 do
|
||||||
octets[#octets+1] = "0"
|
octets[#octets+1] = "0"
|
||||||
end
|
end
|
||||||
return ( table.concat( octets, "." ) )
|
if family == "inet6" then
|
||||||
|
return ( table.concat( { 0,0,0,0,0,"ffff",
|
||||||
|
stdnse.tohex( 256*octets[1]+octets[2] ),
|
||||||
|
stdnse.tohex( 256*octets[3]+octets[4] )
|
||||||
|
}, ":" ) )
|
||||||
|
else
|
||||||
|
return ( table.concat( octets, "." ) )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if family ~= nil and family ~= "inet6" then
|
||||||
|
return nil, "Error in ipOps.expand_ip: Cannot convert IPv6 address to IPv4"
|
||||||
end
|
end
|
||||||
|
|
||||||
if ip:match( "[^\.:%x]" ) then
|
if ip:match( "[^\.:%x]" ) then
|
||||||
@@ -498,6 +503,39 @@ get_last_ip = function( ip, prefix )
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---
|
||||||
|
-- Converts an IP address into an opaque string.
|
||||||
|
-- @param ip String representing an IPv4 or IPv6 address.
|
||||||
|
-- @param family (optional) Address family to convert to. "ipv6" converts IPv4
|
||||||
|
-- addresses to IPv4-mapped IPv6.
|
||||||
|
-- @usage
|
||||||
|
-- opaque = ipOps.ip_to_str( "192.168.3.4" )
|
||||||
|
-- @return 4- or 16-byte string representing IP address (or <code>nil</code>
|
||||||
|
-- in case of an error).
|
||||||
|
-- @return String error message in case of an error
|
||||||
|
ip_to_str = function( ip, family )
|
||||||
|
local err
|
||||||
|
|
||||||
|
ip, err = expand_ip( ip, family )
|
||||||
|
if err then return nil, err end
|
||||||
|
|
||||||
|
local t = {}
|
||||||
|
|
||||||
|
if not ip:match( ":" ) then
|
||||||
|
-- ipv4 string
|
||||||
|
for octet in string.gmatch( ip, "%d+" ) do
|
||||||
|
t[#t+1] = bin.pack( ">C", tonumber(octet) )
|
||||||
|
end
|
||||||
|
else
|
||||||
|
-- ipv6 string
|
||||||
|
for hdt in string.gmatch( ip, "%x+" ) do
|
||||||
|
t[#t+1] = bin.pack( ">S", tonumber(hdt, 16) )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
return table.concat( t )
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -40,30 +40,16 @@ require("target")
|
|||||||
require("http")
|
require("http")
|
||||||
|
|
||||||
Util = {
|
Util = {
|
||||||
|
|
||||||
--- Converts a string ip to a numeric value suitable for comparing
|
|
||||||
--
|
|
||||||
-- @param ip string containing the ip to convert
|
|
||||||
-- @return number containing the converted ip
|
|
||||||
ipToNumber = function(ip)
|
|
||||||
local o1, o2, o3, o4 = ip:match("^(%d*)%.(%d*)%.(%d*)%.(%d*)$")
|
|
||||||
return (256^3) * o1 + (256^2) * o2 + (256^1) * o3 + (256^0) * o4
|
|
||||||
end,
|
|
||||||
|
|
||||||
--- Compare function used for sorting IP-addresses
|
--- Compare function used for sorting IP-addresses
|
||||||
--
|
--
|
||||||
-- @param a table containing first item
|
-- @param a table containing first item
|
||||||
-- @param b table containing second item
|
-- @param b table containing second item
|
||||||
-- @return true if the port of a is less than the port of b
|
-- @return true if a is less than b
|
||||||
ipCompare = function(a, b)
|
ipCompare = function(a, b)
|
||||||
local ip_a = Util.ipToNumber(a.name)
|
return ipOps.compare_ip(a, "lt", b)
|
||||||
local ip_b = Util.ipToNumber(b.name)
|
end,
|
||||||
if ( tonumber(ip_a) < tonumber(ip_b) ) then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Comm = {
|
Comm = {
|
||||||
@@ -293,7 +279,8 @@ Comm = {
|
|||||||
setMulticast = function( self, mcast )
|
setMulticast = function( self, mcast )
|
||||||
assert( type(mcast)=="boolean", "mcast has to be either true or false")
|
assert( type(mcast)=="boolean", "mcast has to be either true or false")
|
||||||
self.mcast = mcast
|
self.mcast = mcast
|
||||||
self.host = "239.255.255.250"
|
local family = nmap.address_family()
|
||||||
|
self.host = (family=="inet6" and "FF02::C" or "239.255.255.250")
|
||||||
self.port = 1900
|
self.port = 1900
|
||||||
end,
|
end,
|
||||||
|
|
||||||
@@ -351,4 +338,4 @@ Helper = {
|
|||||||
return status, response
|
return status, response
|
||||||
end,
|
end,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -322,8 +322,10 @@ Helper = {
|
|||||||
-- @param mcast boolean true if multicast is to be used, false otherwise
|
-- @param mcast boolean true if multicast is to be used, false otherwise
|
||||||
setMulticast = function( self, mcast )
|
setMulticast = function( self, mcast )
|
||||||
assert( type(mcast)=="boolean", "mcast has to be either true or false")
|
assert( type(mcast)=="boolean", "mcast has to be either true or false")
|
||||||
|
local family = nmap.address_family()
|
||||||
self.mcast = mcast
|
self.mcast = mcast
|
||||||
self.host, self.port = "239.255.255.250", 3702
|
self.host = (family=="inet6" and "FF02::C" or "239.255.255.250")
|
||||||
|
self.port = 3702
|
||||||
end,
|
end,
|
||||||
|
|
||||||
--- Sets the timeout for socket reads
|
--- Sets the timeout for socket reads
|
||||||
|
|||||||
@@ -1059,8 +1059,9 @@ function output_ips(t)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- IPv6 - for now, no sorting.
|
-- IPv6
|
||||||
-- Rows are allowed to be 71 chars wide
|
-- Rows are allowed to be 71 chars wide
|
||||||
|
table.sort(t['6'], function(a,b) return ipOps.compare_ip(a, "lt", b) end)
|
||||||
local i = 1
|
local i = 1
|
||||||
local limit = #t['6']
|
local limit = #t['6']
|
||||||
while i <= limit do
|
while i <= limit do
|
||||||
|
|||||||
Reference in New Issue
Block a user