mirror of
https://github.com/nmap/nmap.git
synced 2025-12-07 13:11:28 +00:00
http.lua: Reuse constant objects instead of creating them
This commit is contained in:
@@ -302,6 +302,7 @@ local function skip_lws(s, pos)
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local digestauth_required = {"username","realm","nonce","digest-uri","response"}
|
||||||
---Validate an 'options' table, which is passed to a number of the HTTP functions. It is
|
---Validate an 'options' table, which is passed to a number of the HTTP functions. It is
|
||||||
-- often difficult to track down a mistake in the options table, and requires fiddling
|
-- often difficult to track down a mistake in the options table, and requires fiddling
|
||||||
-- with the http.lua source, but this should make that a lot easier.
|
-- with the http.lua source, but this should make that a lot easier.
|
||||||
@@ -379,8 +380,7 @@ local function validate_options(options)
|
|||||||
end
|
end
|
||||||
elseif (key == 'digestauth') then
|
elseif (key == 'digestauth') then
|
||||||
if(type(value) == 'table') then
|
if(type(value) == 'table') then
|
||||||
local req_keys = {"username","realm","nonce","digest-uri","response"}
|
for _,k in ipairs(digestauth_required) do
|
||||||
for _,k in ipairs(req_keys) do
|
|
||||||
if not value[k] then
|
if not value[k] then
|
||||||
stdnse.debug1("http: options.digestauth missing key: %s",k)
|
stdnse.debug1("http: options.digestauth missing key: %s",k)
|
||||||
bad = true
|
bad = true
|
||||||
@@ -1030,6 +1030,10 @@ end
|
|||||||
-- size: The size of the record, equal to #record.result.body.
|
-- size: The size of the record, equal to #record.result.body.
|
||||||
local cache = {size = 0};
|
local cache = {size = 0};
|
||||||
|
|
||||||
|
local function cmp_last_used (r1, r2)
|
||||||
|
return (r1.last_used or 0) < (r2.last_used or 0);
|
||||||
|
end
|
||||||
|
|
||||||
local function check_size (cache)
|
local function check_size (cache)
|
||||||
local max_size = tonumber(stdnse.get_script_args({'http.max-cache-size', 'http-max-cache-size'}) or 1e6);
|
local max_size = tonumber(stdnse.get_script_args({'http.max-cache-size', 'http-max-cache-size'}) or 1e6);
|
||||||
|
|
||||||
@@ -1039,9 +1043,7 @@ local function check_size (cache)
|
|||||||
stdnse.debug1(
|
stdnse.debug1(
|
||||||
"Current http cache size (%d bytes) exceeds max size of %d",
|
"Current http cache size (%d bytes) exceeds max size of %d",
|
||||||
size, max_size);
|
size, max_size);
|
||||||
table.sort(cache, function(r1, r2)
|
table.sort(cache, cmp_last_used);
|
||||||
return (r1.last_used or 0) < (r2.last_used or 0);
|
|
||||||
end);
|
|
||||||
|
|
||||||
for i, record in ipairs(cache) do
|
for i, record in ipairs(cache) do
|
||||||
if size <= max_size then break end
|
if size <= max_size then break end
|
||||||
@@ -1593,6 +1595,9 @@ function put(host, port, path, options, putdata)
|
|||||||
return generic_request(host, port, "PUT", path, mod_options)
|
return generic_request(host, port, "PUT", path, mod_options)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function domain (h)
|
||||||
|
return (h:match("%..+%..+") or h):lower()
|
||||||
|
end
|
||||||
-- A battery of tests a URL is subjected to in order to decide if it may be
|
-- A battery of tests a URL is subjected to in order to decide if it may be
|
||||||
-- redirected to.
|
-- redirected to.
|
||||||
local redirect_ok_rules = {
|
local redirect_ok_rules = {
|
||||||
@@ -1614,7 +1619,6 @@ local redirect_ok_rules = {
|
|||||||
if hostname == host.ip then
|
if hostname == host.ip then
|
||||||
return url.host == hostname
|
return url.host == hostname
|
||||||
end
|
end
|
||||||
local domain = function (h) return (h:match("%..+%..+") or h):lower() end
|
|
||||||
return domain(hostname) == domain(url.host)
|
return domain(hostname) == domain(url.host)
|
||||||
end,
|
end,
|
||||||
|
|
||||||
@@ -1710,6 +1714,7 @@ function parse_redirect(host, port, path, response)
|
|||||||
return u
|
return u
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local ret_false = function () return false end
|
||||||
-- Retrieves the correct function to use to validate HTTP redirects
|
-- Retrieves the correct function to use to validate HTTP redirects
|
||||||
-- @param host table as received by the action function
|
-- @param host table as received by the action function
|
||||||
-- @param port table as received by the action function
|
-- @param port table as received by the action function
|
||||||
@@ -1718,7 +1723,7 @@ end
|
|||||||
local function get_redirect_ok(host, port, options)
|
local function get_redirect_ok(host, port, options)
|
||||||
if ( options ) then
|
if ( options ) then
|
||||||
if ( options.redirect_ok == false ) then
|
if ( options.redirect_ok == false ) then
|
||||||
return function() return false end
|
return ret_false
|
||||||
elseif( "function" == type(options.redirect_ok) ) then
|
elseif( "function" == type(options.redirect_ok) ) then
|
||||||
return options.redirect_ok(host, port)
|
return options.redirect_ok(host, port)
|
||||||
elseif( type(options.redirect_ok) == "number") then
|
elseif( type(options.redirect_ok) == "number") then
|
||||||
@@ -1963,6 +1968,7 @@ local function force_header (headers, header, value)
|
|||||||
return headers
|
return headers
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local pipeline_comm_opts = {recv_before=false, request_timeout=10000}
|
||||||
---Performs all queued requests in the all_requests variable (created by the
|
---Performs all queued requests in the all_requests variable (created by the
|
||||||
-- <code>pipeline_add</code> function).
|
-- <code>pipeline_add</code> function).
|
||||||
--
|
--
|
||||||
@@ -1992,7 +1998,7 @@ function pipeline_go(host, port, all_requests)
|
|||||||
local req = all_requests[1]
|
local req = all_requests[1]
|
||||||
req.options.header = force_header(req.options.header, "Connection", "keep-alive")
|
req.options.header = force_header(req.options.header, "Connection", "keep-alive")
|
||||||
local reqstr = build_request(host, port, req.method, req.path, req.options)
|
local reqstr = build_request(host, port, req.method, req.path, req.options)
|
||||||
local socket, partial, bopt = comm.tryssl(host, port, reqstr, {recv_before=false, request_timeout=10000})
|
local socket, partial, bopt = comm.tryssl(host, port, reqstr, pipeline_comm_opts)
|
||||||
if not socket then
|
if not socket then
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
@@ -2558,6 +2564,16 @@ local function cache_404_response(host, port, response)
|
|||||||
return table.unpack(response)
|
return table.unpack(response)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local bad_responses = { 301, 302, 400, 401, 403, 499, 501, 503 }
|
||||||
|
local identify_404_get_opts = {redirect_ok=false}
|
||||||
|
local identify_404_cache_404 = {true, 404}
|
||||||
|
local identify_404_cache_unknown = {false,
|
||||||
|
"Two known 404 pages returned valid and different pages; unable to identify valid response."
|
||||||
|
}
|
||||||
|
local identify_404_cache_unknown_folder = {false,
|
||||||
|
"Two known 404 pages returned valid and different pages; unable to identify valid response (happened when checking a folder)."
|
||||||
|
}
|
||||||
|
local identify_404_cache_200 = {true, 200}
|
||||||
---Try requesting a non-existent file to determine how the server responds to
|
---Try requesting a non-existent file to determine how the server responds to
|
||||||
-- unknown pages ("404 pages")
|
-- unknown pages ("404 pages")
|
||||||
--
|
--
|
||||||
@@ -2602,14 +2618,13 @@ function identify_404(host, port)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
local data
|
local data
|
||||||
local bad_responses = { 301, 302, 400, 401, 403, 499, 501, 503 }
|
|
||||||
|
|
||||||
-- The URLs used to check 404s
|
-- The URLs used to check 404s
|
||||||
local URL_404_1 = '/nmaplowercheck' .. os.time(os.date('*t'))
|
local URL_404_1 = '/nmaplowercheck' .. os.time(os.date('*t'))
|
||||||
local URL_404_2 = '/NmapUpperCheck' .. os.time(os.date('*t'))
|
local URL_404_2 = '/NmapUpperCheck' .. os.time(os.date('*t'))
|
||||||
local URL_404_3 = '/Nmap/folder/check' .. os.time(os.date('*t'))
|
local URL_404_3 = '/Nmap/folder/check' .. os.time(os.date('*t'))
|
||||||
|
|
||||||
data = get(host, port, URL_404_1,{redirect_ok=false})
|
data = get(host, port, URL_404_1, identify_404_get_opts)
|
||||||
if(data == nil) then
|
if(data == nil) then
|
||||||
stdnse.debug1("HTTP: Failed while testing for 404 status code")
|
stdnse.debug1("HTTP: Failed while testing for 404 status code")
|
||||||
-- do not cache; maybe it will work next time?
|
-- do not cache; maybe it will work next time?
|
||||||
@@ -2618,7 +2633,7 @@ function identify_404(host, port)
|
|||||||
|
|
||||||
if(data.status and data.status == 404) then
|
if(data.status and data.status == 404) then
|
||||||
stdnse.debug1("HTTP: Host returns proper 404 result.")
|
stdnse.debug1("HTTP: Host returns proper 404 result.")
|
||||||
return cache_404_response(host, port, {true, 404})
|
return cache_404_response(host, port, identify_404_cache_404)
|
||||||
end
|
end
|
||||||
|
|
||||||
if(data.status and data.status == 200) then
|
if(data.status and data.status == 200) then
|
||||||
@@ -2666,17 +2681,13 @@ function identify_404(host, port)
|
|||||||
if(clean_body ~= clean_body2) then
|
if(clean_body ~= clean_body2) then
|
||||||
stdnse.debug1("HTTP: Two known 404 pages returned valid and different pages; unable to identify valid response.")
|
stdnse.debug1("HTTP: Two known 404 pages returned valid and different pages; unable to identify valid response.")
|
||||||
stdnse.debug1("HTTP: If you investigate the server and it's possible to clean up the pages, please post to nmap-dev mailing list.")
|
stdnse.debug1("HTTP: If you investigate the server and it's possible to clean up the pages, please post to nmap-dev mailing list.")
|
||||||
return cache_404_response(host, port, {false,
|
return cache_404_response(host, port, identify_404_cache_unknown)
|
||||||
"Two known 404 pages returned valid and different pages; unable to identify valid response."
|
|
||||||
})
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if(clean_body ~= clean_body3) then
|
if(clean_body ~= clean_body3) then
|
||||||
stdnse.debug1("HTTP: Two known 404 pages returned valid and different pages; unable to identify valid response (happened when checking a folder).")
|
stdnse.debug1("HTTP: Two known 404 pages returned valid and different pages; unable to identify valid response (happened when checking a folder).")
|
||||||
stdnse.debug1("HTTP: If you investigate the server and it's possible to clean up the pages, please post to nmap-dev mailing list.")
|
stdnse.debug1("HTTP: If you investigate the server and it's possible to clean up the pages, please post to nmap-dev mailing list.")
|
||||||
return cache_404_response(host, port, {false,
|
return cache_404_response(host, port, identify_404_cache_unknown_folder)
|
||||||
"Two known 404 pages returned valid and different pages; unable to identify valid response (happened when checking a folder)."
|
|
||||||
})
|
|
||||||
end
|
end
|
||||||
|
|
||||||
cache_404_response(host, port, {true, 200, clean_body})
|
cache_404_response(host, port, {true, 200, clean_body})
|
||||||
@@ -2684,7 +2695,7 @@ function identify_404(host, port)
|
|||||||
end
|
end
|
||||||
|
|
||||||
stdnse.debug1("HTTP: The 200 response didn't contain a body.")
|
stdnse.debug1("HTTP: The 200 response didn't contain a body.")
|
||||||
return cache_404_response(host, port, {true, 200})
|
return cache_404_response(host, port, identify_404_cache_200)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Loop through any expected error codes
|
-- Loop through any expected error codes
|
||||||
@@ -2764,6 +2775,12 @@ function page_exists(data, result_404, known_404, page, displayall)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local lowercase = function (p)
|
||||||
|
return (p or ''):lower()
|
||||||
|
end
|
||||||
|
local safe_string = function (p)
|
||||||
|
return p or ''
|
||||||
|
end
|
||||||
---Check if the response variable contains the given text.
|
---Check if the response variable contains the given text.
|
||||||
--
|
--
|
||||||
-- Response variable could be a return from a http.get, http.post,
|
-- Response variable could be a return from a http.get, http.post,
|
||||||
@@ -2792,10 +2809,7 @@ function response_contains(response, pattern, case_sensitive)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Create a function that either lowercases everything or doesn't, depending on case sensitivity
|
-- Create a function that either lowercases everything or doesn't, depending on case sensitivity
|
||||||
local case = function(pattern) return string.lower(pattern or '') end
|
local case = case_sensitive and safe_string or lowercase
|
||||||
if(case_sensitive == true) then
|
|
||||||
case = function(pattern) return (pattern or '') end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Set the case of the pattern
|
-- Set the case of the pattern
|
||||||
pattern = case(pattern)
|
pattern = case(pattern)
|
||||||
|
|||||||
Reference in New Issue
Block a user