mirror of
https://github.com/nmap/nmap.git
synced 2025-12-28 02:19:04 +00:00
o Added a new NSE Comm library for common network discovery tasks such
as banner-grabbing (get_banner()) and making a quick exchange of data (exchange()). 16 scripts were updated to use this library. [Kris] I have *not* been able to test all of these scripts; however, I have reviewed them and they should all work properly. I would really like some more testing, though :) This commit includes scripting.xml documentation.
This commit is contained in:
151
nselib/comm.lua
Normal file
151
nselib/comm.lua
Normal file
@@ -0,0 +1,151 @@
|
||||
-- Kris Katterjohn 04/2008
|
||||
|
||||
module(..., package.seeall)
|
||||
|
||||
------
|
||||
--
|
||||
-- The Functions:
|
||||
--
|
||||
-- get_banner(host, port, [opts])
|
||||
-- exchange(host, port, data, [opts])
|
||||
--
|
||||
-- get_banner() does just what it sounds like it does: connects to the
|
||||
-- host, reads whatever it gives us, and then returns it.
|
||||
--
|
||||
-- exchange() connects to the host, sends the requested data, reads
|
||||
-- whatever it gives us, and then returns it.
|
||||
--
|
||||
-- Both of these functions return multiple values so that they can be
|
||||
-- used with exception handling via nmap.new_try(). The second value
|
||||
-- they return is either the response from the host, or the error message
|
||||
-- from one of the previous calls (connect, send, receive*).
|
||||
--
|
||||
-- These functions can be passed a table of options with the following keys:
|
||||
--
|
||||
-- bytes: Specifies the minimum amount of bytes are to be read from the host
|
||||
-- lines: Specifies the minimum amount of lines are to be read from the host
|
||||
-- proto: Specifies the protocol to be used with the connect() call
|
||||
-- timeout: Sets the socket's timeout with nmap.set_timeout()
|
||||
--
|
||||
-- If neither lines nor bytes are specified, the calls read as many lines
|
||||
-- as possible. If only bytes if specified, then it only tries to read that
|
||||
-- many bytes. Likewise, it only lines if specified, then it only tries to
|
||||
-- read that many lines. If they're both specified, the lines value is used.
|
||||
--
|
||||
------
|
||||
|
||||
-- Makes sure that opts exists and the default proto is there
|
||||
local initopts = function(opts)
|
||||
if not opts then
|
||||
opts = {}
|
||||
end
|
||||
|
||||
if not opts.proto then
|
||||
opts.proto = "tcp"
|
||||
end
|
||||
|
||||
return opts
|
||||
end
|
||||
|
||||
-- Sets up the socket and connects to host:port
|
||||
local setup_connect = function(host, port, opts)
|
||||
if type(host) ~= "table" then
|
||||
host = {ip = host}
|
||||
end
|
||||
|
||||
local target = host.targetname or host.ip or host.name
|
||||
|
||||
if type(port) ~= "table" then
|
||||
port = {number = port}
|
||||
end
|
||||
|
||||
local sock = nmap.new_socket()
|
||||
|
||||
if opts.timeout then
|
||||
sock:set_timeout(opts.timeout)
|
||||
end
|
||||
|
||||
local status, err = sock:connect(target, port.number, opts.proto)
|
||||
|
||||
if not status then
|
||||
return status, err
|
||||
end
|
||||
|
||||
return true, sock
|
||||
end
|
||||
|
||||
local read = function(sock, opts)
|
||||
local line, response, status
|
||||
|
||||
if opts.lines then
|
||||
status, response = sock:receive_lines(opts.lines)
|
||||
return status, response
|
||||
elseif opts.bytes then
|
||||
status, response = sock:receive_bytes(opts.bytes)
|
||||
return status, response
|
||||
end
|
||||
|
||||
response = ""
|
||||
|
||||
while true do
|
||||
status, line = sock:receive_lines(1)
|
||||
|
||||
if not status then
|
||||
break
|
||||
end
|
||||
|
||||
response = response .. line
|
||||
end
|
||||
|
||||
-- Either we reached the end of the stream, or we got all we could
|
||||
-- within the socket timeout
|
||||
if line == "EOF" or (line == "TIMEOUT" and response ~= "") then
|
||||
return true, response
|
||||
end
|
||||
|
||||
return false, line
|
||||
end
|
||||
|
||||
get_banner = function(host, port, opts)
|
||||
opts = initopts(opts)
|
||||
|
||||
local status, sock = setup_connect(host, port, opts)
|
||||
local ret
|
||||
|
||||
if not status then
|
||||
-- sock is an error message in this case
|
||||
return status, sock
|
||||
end
|
||||
|
||||
status, ret = read(sock, opts)
|
||||
|
||||
sock:close()
|
||||
|
||||
return status, ret
|
||||
end
|
||||
|
||||
exchange = function(host, port, data, opts)
|
||||
opts = initopts(opts)
|
||||
|
||||
local status, sock = setup_connect(host, port, opts)
|
||||
local ret
|
||||
|
||||
if not status then
|
||||
-- sock is an error message in this case
|
||||
return status, sock
|
||||
end
|
||||
|
||||
status, ret = sock:send(data)
|
||||
|
||||
if not status then
|
||||
sock:close()
|
||||
return status, ret
|
||||
end
|
||||
|
||||
status, ret = read(sock, opts)
|
||||
|
||||
sock:close()
|
||||
|
||||
return status, ret
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user