From 54a8caae65e3308adcfaef0a97a90b3fe02ac012 Mon Sep 17 00:00:00 2001 From: david Date: Sun, 1 Mar 2009 19:02:33 +0000 Subject: [PATCH] Make http.request conform to its documentation; it now interprets any header fields passed to it and adds them to the request. Previously it ignored them, relying on http.get to concatentate the header fields into a string for it. --- nselib/http.lua | 56 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 15 deletions(-) diff --git a/nselib/http.lua b/nselib/http.lua index 107a0c49a..59f7678d1 100644 --- a/nselib/http.lua +++ b/nselib/http.lua @@ -34,6 +34,27 @@ local stdnse = require 'stdnse' -- 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 +--- Recursively copy into a table any elements from another table whose key it +-- doesn't have. +local function table_augment(to, from) + for k, v in pairs(from) do + if to[v] then + table_copy(to[v], from[v]) + else + to[v] = from[v] + end + end +end + +--- Get a suitable hostname string from the argument, which may be either a +-- string or a host table. +local function get_hostname(host) + if type(host) == "table" then + return host.targetname or ( host.name ~= '' and host.name ) or host.ip + else + return host + end +end --- Fetches a resource with a GET request. -- @@ -51,23 +72,21 @@ local stdnse = require 'stdnse' -- @see http.request get = function( host, port, path, options ) options = options or {} - local presets = {Host=host,Connection="close",['User-Agent']="Mozilla/5.0 (compatible; Nmap Scripting Engine; http://nmap.org/book/nse.html)"} - if type(host) == 'table' then - presets['Host'] = host.targetname or ( 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 + -- Private copy of the options table, used to add default header fields. + local mod_options = { + header = { + Host = get_hostname(host), + Connection = "close", + ["User-Agent"] = "Mozilla/5.0 (compatible; Nmap Scripting Engine; http://nmap.org/book/nse.html)" + } + } + -- Add any other options into the local copy. + table_augment(mod_options, options) - 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" + local data = "GET " .. path .. " HTTP/1.1\r\n" - return request( host, port, data, options ) + return request( host, port, data, mod_options ) end --- Parses a URL and calls http.get with the result. @@ -111,7 +130,8 @@ end -- a table for further options. -- @param host The host to query. -- @param port The port on the host. --- @param data Data to send initially to the host. +-- @param data Data to send initially to the host, like a GET line. +-- Should end in a single \r\n. -- @param options A table of options. It may have any of these fields: -- * timeout: A timeout used for socket operations. -- * header: A table containing additional headers to be used for the request. @@ -134,6 +154,12 @@ request = function( host, port, data, options ) port = port.number end + -- Build the header. + for key, value in pairs(options.header or {}) do + data = data .. key .. ": " .. value .. "\r\n" + end + data = data .. "\r\n" + local result = {status=nil,["status-line"]=nil,header={},body=""} local socket = nmap.new_socket() local default_timeout = {}