mirror of
https://github.com/nmap/nmap.git
synced 2025-12-24 08:29:04 +00:00
oops -- forgot to add this when I committed the other http library changes. Thanks to Kris for noticing the omission
This commit is contained in:
149
nselib/http.lua
Normal file
149
nselib/http.lua
Normal file
@@ -0,0 +1,149 @@
|
||||
-- See nmaps COPYING for licence
|
||||
module(...,package.seeall)
|
||||
|
||||
require 'stdnse'
|
||||
require 'url'
|
||||
|
||||
--
|
||||
-- http.get( host, port, path, options )
|
||||
-- http.request( host, port, request, options )
|
||||
-- http.get_url( url, options )
|
||||
--
|
||||
-- host may either be a string or table
|
||||
-- port may either be a number or a table
|
||||
--
|
||||
-- the format of the return value is a table with the following structure:
|
||||
-- {status = 200, header = {}, body ="<html>...</html>"}
|
||||
-- the header table has an entry for each received header with the header name being the key
|
||||
-- the table also has an entry named "status" which contains the http status code of the request
|
||||
-- in case of an error status is nil
|
||||
|
||||
|
||||
-- fetch relative URL with get request
|
||||
get = function( host, port, path, options )
|
||||
options = options or {}
|
||||
local presets = {Host=host,Connection="close",['User-Agent']="Nmap NSE"}
|
||||
if type(host) == 'table' then
|
||||
presets['Host'] = ( host.name ~= '' and host.name ) or host.ip
|
||||
end
|
||||
|
||||
local header = options.header or {}
|
||||
for key,value in pairs(presets) do
|
||||
header[key] = header[key] or value
|
||||
end
|
||||
|
||||
local data = "GET "..path.." HTTP/1.1\r\n"
|
||||
for key,value in pairs(header) do
|
||||
data = data .. key .. ": " .. value .. "\r\n"
|
||||
end
|
||||
data = data .. "\r\n"
|
||||
|
||||
return request( host, port, data, options )
|
||||
end
|
||||
|
||||
-- fetch URL with get request
|
||||
get_url = function( u, options )
|
||||
local parsed = url.parse( u )
|
||||
local port = {}
|
||||
|
||||
port.service = parsed.scheme
|
||||
port.number = parsed.port
|
||||
|
||||
if not port.number then
|
||||
if parsed.scheme == 'https' then
|
||||
port.number = 443
|
||||
else
|
||||
port.number = 80
|
||||
end
|
||||
end
|
||||
|
||||
local path = parsed.path or "/"
|
||||
if parsed.query then
|
||||
path = path .. "?" .. parsed.query
|
||||
end
|
||||
|
||||
return get( parsed.host, port, path, options )
|
||||
end
|
||||
|
||||
-- send http request and return the result as table
|
||||
-- host may be a table or the hostname
|
||||
-- port may be a table or the portnumber
|
||||
request = function( host, port, data, options )
|
||||
options = options or {}
|
||||
|
||||
if type(host) == 'table' then
|
||||
host = ( host.name ~= '' and host.name ) or host.ip
|
||||
end
|
||||
|
||||
local protocol = 'tcp'
|
||||
if type(port) == 'table' then
|
||||
if port.service == 'https' or ( port.version and port.version.service_tunnel == 'ssl' ) then
|
||||
protocol = 'ssl'
|
||||
end
|
||||
port = port.number
|
||||
end
|
||||
|
||||
local result = {status=nil,header={},body=""}
|
||||
local socket = nmap.new_socket()
|
||||
if options.timeout then
|
||||
socket:set_timeout( options.timeout )
|
||||
end
|
||||
if not socket:connect( host, port, protocol ) then
|
||||
return result
|
||||
end
|
||||
if not socket:send( data ) then
|
||||
return result
|
||||
end
|
||||
|
||||
local buffer = stdnse.make_buffer( socket, "\r?\n" )
|
||||
|
||||
local status, line, _
|
||||
local header, body = {}, {}
|
||||
|
||||
-- header loop
|
||||
while true do
|
||||
status, line = buffer()
|
||||
if (not status or line == "") then break end
|
||||
table.insert(header,line)
|
||||
end
|
||||
|
||||
-- build nicer table for header
|
||||
local last_header, match
|
||||
for number, line in pairs( header ) do
|
||||
if number == 1 then
|
||||
local code
|
||||
_, _, code = string.find( line, "HTTP/%d\.%d (%d+)")
|
||||
result.status = tonumber(code)
|
||||
else
|
||||
match, _, key, value = string.find( line, "(.+): (.*)" )
|
||||
if match and key and value then
|
||||
key = key:lower()
|
||||
if result.header[key] then
|
||||
result.header[key] = result.header[key] .. ',' .. value
|
||||
else
|
||||
result.header[key] = value
|
||||
end
|
||||
last_header = key
|
||||
else
|
||||
match, _, value = string.find( line, " +(.*)" )
|
||||
if match and value then
|
||||
result.header[last_header] = result.header[last_header] .. ',' .. value
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- body loop
|
||||
while true do
|
||||
status, line = buffer()
|
||||
if (not status) then break end
|
||||
table.insert(body,line)
|
||||
end
|
||||
|
||||
socket:close()
|
||||
result.body = table.concat( body, "\n" )
|
||||
|
||||
return result
|
||||
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user