1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-06 04:31:29 +00:00

Consolidate some error handling, standardize geoip coordinates, fix output bugs. Fixes #1744

This commit is contained in:
dmiller
2019-09-20 04:40:20 +00:00
parent 634fc19089
commit 3c24eda4be
7 changed files with 138 additions and 89 deletions

View File

@@ -1,6 +1,7 @@
local nmap = require "nmap" local nmap = require "nmap"
local stdnse = require "stdnse" local stdnse = require "stdnse"
local table = require "table" local table = require "table"
local coroutine = require "coroutine"
_ENV = stdnse.module("geoip", stdnse.seeall) _ENV = stdnse.module("geoip", stdnse.seeall)
@@ -72,4 +73,66 @@ get_all_by_gps = function()
return t return t
end end
-- Order in which field names will be shown in XML
local field_order = {
"latitude",
"longitude",
"city",
"region",
"country"
}
--- Location object
--
-- The object supports setting the following fields using functions like
-- <code>set_fieldname</code>:
-- * latitude
-- * longitude
-- * city
-- * region
-- * country
--
-- The location object is suitable for returning from a script, and will
-- produce appropriate string and structured XML output.
Location = {
new = function(self,o)
o = o or {}
setmetatable(o, self)
self.__index = self
return o
end,
-- Ensure fields are put in the XML in proper order
__pairs = function(self)
local function iterator ()
for i, key in ipairs(field_order) do
coroutine.yield(key, self[key])
end
end
return coroutine.wrap(iterator)
end,
__tostring = function(self)
local out = {
("coordinates: %s, %s"):format(self.latitude, self.longitude)
}
-- if any of these are nil, it doesn't increase #place
local place = {self.city}
place[#place+1] = self.region
place[#place+1] = self.country
if #place > 0 then
out[#out+1] = ("location: %s"):format(table.concat(place, ", "))
end
return table.concat(out, "\n")
end,
}
-- Generate setter functions
for _, field in ipairs(field_order) do
Location["set_" .. field] = function(self, value)
self[field] = value
end
end
return _ENV; return _ENV;

View File

@@ -4,6 +4,7 @@ local ipOps = require "ipOps"
local json = require "json" local json = require "json"
local stdnse = require "stdnse" local stdnse = require "stdnse"
local table = require "table" local table = require "table"
local oops = require "oops"
description = [[ description = [[
Tries to identify the physical location of an IP address using the Tries to identify the physical location of an IP address using the
@@ -17,9 +18,13 @@ is no limit on lookups using this service.
-- --
-- @output -- @output
-- | ip-geolocation-geoplugin: -- | ip-geolocation-geoplugin:
-- | 74.207.244.221 (scanme.nmap.org) -- | coordinates: 39.4208984375, -74.497703552246
-- | coordinates (lat,lon): 39.4208984375,-74.497703552246 -- |_location: New Jersey, United States
-- |_ state: New Jersey, United States -- @xmloutput
-- <elem key="latitude">37.5605</elem>
-- <elem key="longitude">-121.9999</elem>
-- <elem key="region">California</elem>
-- <elem key="country">United States</elem>
-- --
-- @see ip-geolocation-ipinfodb.nse -- @see ip-geolocation-ipinfodb.nse
-- @see ip-geolocation-map-bing.nse -- @see ip-geolocation-map-bing.nse
@@ -44,15 +49,18 @@ end
-- No limit on requests -- No limit on requests
local geoplugin = function(ip) local geoplugin = function(ip)
local response = http.get("www.geoplugin.net", 80, "/json.gp?ip="..ip, {any_af=true}) local response = http.get("www.geoplugin.net", 80, "/json.gp?ip="..ip, {any_af=true})
local stat, loc = json.parse(response.body) local stat, loc = oops.raise(
"The geoPlugin service has likely blocked you due to excessive usage",
json.parse(response.body))
if not stat then if not stat then
return false, loc return stat, loc
end end
local output = {} local output = geoip.Location:new()
table.insert(output, "coordinates (lat,lon): "..loc.geoplugin_latitude..","..loc.geoplugin_longitude) output:set_latitude(loc.geoplugin_latitude)
local regionName = (loc.geoplugin_regionName == json.NULL) and "Unknown" or loc.geoplugin_regionName output:set_longitude(loc.geoplugin_longitude)
table.insert(output,"state: ".. regionName ..", ".. loc.geoplugin_countryName) output:set_region((loc.geoplugin_regionName == json.NULL) and "Unknown" or loc.geoplugin_regionName)
output:set_country(loc.geoplugin_countryName)
geoip.add(ip, loc.geoplugin_latitude, loc.geoplugin_longitude) geoip.add(ip, loc.geoplugin_latitude, loc.geoplugin_longitude)
@@ -60,21 +68,5 @@ local geoplugin = function(ip)
end end
action = function(host,port) action = function(host,port)
local output = stdnse.output_table() return oops.output(geoplugin(host.ip))
local status, result = geoplugin(host.ip)
if not status then
if result == "syntax error" then
result = "The geoPlugin service has likely blocked you due to excessive usage, but the response received was 'syntax error'."
end
output.ERROR = result
return output, output.ERROR
end
output.name = host.ip
if host.targetname then
output.name = output.name.." ("..host.targetname..")"
end
return stdnse.format_output(true,output)
end end

View File

@@ -2,6 +2,7 @@ local geoip = require "geoip"
local http = require "http" local http = require "http"
local ipOps = require "ipOps" local ipOps = require "ipOps"
local json = require "json" local json = require "json"
local oops = require "oops"
local stdnse = require "stdnse" local stdnse = require "stdnse"
local table = require "table" local table = require "table"
@@ -24,9 +25,15 @@ needs to be obtained through free registration for this service:
-- --
-- @output -- @output
-- | ip-geolocation-ipinfodb: -- | ip-geolocation-ipinfodb:
-- | 74.207.244.221 (scanme.nmap.org) -- | coordinates: 37.5384, -121.99
-- | coordinates (lat,lon): 37.5384,-121.99 -- |_location: FREMONT, CALIFORNIA, UNITED STATES
-- |_ city: FREMONT, CALIFORNIA, UNITED STATES --
-- @xmloutput
-- <elem key="latitude">37.5384</elem>
-- <elem key="longitude">-121.99</elem>
-- <elem key="city">FREMONT</elem>
-- <elem key="region">CALIFORNIA</elem>
-- <elem key="country">UNITED STATES</elem>
-- --
-- @see ip-geolocation-geoplugin.nse -- @see ip-geolocation-geoplugin.nse
-- @see ip-geolocation-map-bing.nse -- @see ip-geolocation-map-bing.nse
@@ -62,34 +69,28 @@ end
local ipinfodb = function(ip) local ipinfodb = function(ip)
local api_key = stdnse.get_script_args(SCRIPT_NAME..".apikey") local api_key = stdnse.get_script_args(SCRIPT_NAME..".apikey")
local response = http.get("api.ipinfodb.com", 80, "/v3/ip-city/?key="..api_key.."&format=json".."&ip="..ip, {any_af=true}) local response = http.get("api.ipinfodb.com", 80, "/v3/ip-city/?key="..api_key.."&format=json".."&ip="..ip, {any_af=true})
local stat, loc = json.parse(response.body) local stat, loc = oops.raise(
"Unable to parse ipinfodb.com response",
json.parse(response.body))
if not stat then if not stat then
stdnse.debug1("No response, possibly a network problem.") return stat, loc
return nil
end end
if loc.statusMessage and loc.statusMessage == "Invalid API key." then if loc.statusMessage and loc.statusMessage == "Invalid API key." then
stdnse.debug1(loc.statusMessage) return false, oops.err(loc.statusMessage)
return nil
end end
local output = {} local output = geoip.Location:new()
table.insert(output, "coordinates (lat,lon): "..loc.latitude..","..loc.longitude) output:set_latitude(loc.latitude)
table.insert(output,"city: ".. loc.cityName..", ".. loc.regionName..", ".. loc.countryName) output:set_longitude(loc.longitude)
output:set_city(loc.cityName)
output:set_region(loc.regionName)
output:set_country(loc.countryName)
geoip.add(ip, loc.latitude, loc.longitude) geoip.add(ip, loc.latitude, loc.longitude)
return output return true, output
end end
action = function(host,port) action = function(host,port)
local output = ipinfodb(host.ip) return oops.output(ipinfodb(host.ip))
if(output and #output~=0) then
output.name = host.ip
if host.targetname then
output.name = output.name.." ("..host.targetname..")"
end
end
return stdnse.format_output(true,output)
end end

View File

@@ -1,6 +1,7 @@
local http = require "http" local http = require "http"
local geoip = require "geoip" local geoip = require "geoip"
local io = require "io" local io = require "io"
local oops = require "oops"
local stdnse = require "stdnse" local stdnse = require "stdnse"
local string = require "string" local string = require "string"
local table = require "table" local table = require "table"
@@ -177,21 +178,14 @@ postrule = function()
end end
action = function() action = function()
local output = stdnse.output_table()
-- Parse and sanity check the command line arguments. -- Parse and sanity check the command line arguments.
local status, params, options = parse_args() local status, params, options = oops.raise(
"Script argument problem",
parse_args())
if not status then if not status then
output.ERROR = params return params
return output, output.ERROR
end end
-- Render the map. -- Render the map.
local status, msg = render(params, options) return oops.output(render(params, options))
if not status then
output.ERROR = msg
return output, output.ERROR
end
return output, stdnse.format_output(true, msg)
end end

View File

@@ -1,6 +1,7 @@
local http = require "http" local http = require "http"
local geoip = require "geoip" local geoip = require "geoip"
local io = require "io" local io = require "io"
local oops = require "oops"
local stdnse = require "stdnse" local stdnse = require "stdnse"
local table = require "table" local table = require "table"
local url = require "url" local url = require "url"
@@ -167,21 +168,14 @@ postrule = function()
end end
action = function() action = function()
local output = stdnse.output_table()
-- Parse and sanity check the command line arguments. -- Parse and sanity check the command line arguments.
local status, params, options = parse_args() local status, params, options = oops.raise(
"Script argument problem",
parse_args())
if not status then if not status then
output.ERROR = params return params
return output, output.ERROR
end end
-- Render the map. -- Render the map.
local status, msg = render(params, options) return oops.output(render(params, options))
if not status then
output.ERROR = msg
return output, output.ERROR
end
return output, stdnse.format_output(true, msg)
end end

View File

@@ -1,5 +1,6 @@
local geoip = require "geoip" local geoip = require "geoip"
local io = require "io" local io = require "io"
local oops = require "oops"
local stdnse = require "stdnse" local stdnse = require "stdnse"
local table = require "table" local table = require "table"
@@ -76,21 +77,14 @@ postrule = function()
end end
action = function() action = function()
local output = stdnse.output_table()
-- Parse and sanity check the command line arguments. -- Parse and sanity check the command line arguments.
local status, path = parse_args() local status, path = oops.raise(
"Script argument problem",
parse_args())
if not status then if not status then
output.ERROR = path return path
return output, output.ERROR
end end
-- Render the map. -- Render the map.
local status, msg = render(path) return oops.output(render(path))
if not status then
output.ERROR = msg
return output, output.ERROR
end
return msg
end end

View File

@@ -25,9 +25,15 @@ the commercial ones.
-- --
-- @output -- @output
-- | ip-geolocation-maxmind: -- | ip-geolocation-maxmind:
-- | 74.207.244.221 (scanme.nmap.org) -- | coordinates: 39.4899, -74.4773
-- | coordinates (lat,lon): 39.4899,-74.4773 -- |_location: Absecon, Philadelphia, PA, United States
-- |_ city: Absecon, Philadelphia, PA, United States --
-- @xmloutput
-- <elem key="latitude">39.4899</elem>
-- <elem key="longitude">-74.4773</elem>
-- <elem key="city">Absecon</elem>
-- <elem key="region">Philadelphia, PA</elem>
-- <elem key="country">United States</elem>
-- --
-- @see ip-geolocation-geoplugin.nse -- @see ip-geolocation-geoplugin.nse
-- @see ip-geolocation-ipinfodb.nse -- @see ip-geolocation-ipinfodb.nse
@@ -498,8 +504,13 @@ local GeoIP = {
local loc = self:record_by_addr(addr) local loc = self:record_by_addr(addr)
if not loc then return nil end if not loc then return nil end
geoip.add(addr, loc.latitude, loc.longitude) geoip.add(addr, loc.latitude, loc.longitude)
setmetatable(loc, record_metatable) local output = geoip.Location:new()
return loc output:set_latitude(loc.latitude)
output:set_longitude(loc.longitude)
output:set_city(loc.city)
output:set_region(loc.metro_code)
output:set_country(loc.country_name)
return output
end, end,
record_by_addr=function(self,addr) record_by_addr=function(self,addr)