From 46eca7f35fb78280f225ec3f3dd9bb107b21dbc3 Mon Sep 17 00:00:00 2001 From: dmiller Date: Mon, 27 Aug 2018 22:00:10 +0000 Subject: [PATCH] Move date/time functions from stdnse to datetime. See #517 --- docs/scripting.xml | 6 +- nselib/afp.lua | 7 +- nselib/datetime.lua | 202 ++++++++++++++++++++++++++- nselib/dhcp.lua | 3 +- nselib/dhcp6.lua | 3 +- nselib/ipp.lua | 4 +- nselib/ldap.lua | 3 +- nselib/msrpc.lua | 12 +- nselib/natpmp.lua | 3 +- nselib/rpc.lua | 3 +- nselib/smb.lua | 5 +- nselib/smb2.lua | 5 +- nselib/stdnse.lua | 195 -------------------------- scripts/bitcoin-getaddr.nse | 4 +- scripts/bitcoin-info.nse | 2 +- scripts/clock-skew.nse | 11 +- scripts/gkrellm-info.nse | 3 +- scripts/gpsd-info.nse | 3 +- scripts/http-date.nse | 7 +- scripts/http-icloud-findmyiphone.nse | 4 +- scripts/http-slowloris.nse | 3 +- scripts/memcached-info.nse | 2 +- scripts/ntp-info.nse | 2 +- scripts/openlookup-info.nse | 3 +- scripts/openwebnet-discovery.nse | 3 +- scripts/rfc868-time.nse | 2 +- scripts/rusers.nse | 5 +- scripts/smb-enum-sessions.nse | 5 +- scripts/smb-os-discovery.nse | 2 +- scripts/smb-system-info.nse | 3 +- scripts/snmp-info.nse | 3 +- scripts/snmp-sysdescr.nse | 3 +- scripts/snmp-win32-software.nse | 5 +- scripts/ssl-cert.nse | 5 +- scripts/ssl-date.nse | 6 +- 35 files changed, 282 insertions(+), 255 deletions(-) diff --git a/docs/scripting.xml b/docs/scripting.xml index cf6cf4e5d..b1e1b247a 100644 --- a/docs/scripting.xml +++ b/docs/scripting.xml @@ -2402,13 +2402,13 @@ PORT STATE SERVICE 2012-09-07T23:37:42 - The standard library function - stdnse.format_timestamp code exists to format times + The library function + datetime.format_timestamp code exists to format times for structured output. It takes an optional time zone offset in seconds and automatically shifts the date to be correct within that offset. -stdnse.format_timestamp(os.time(), 0) --> "2012-09-07T23:37:42+00:00" +datetime.format_timestamp(os.time(), 0) --> "2012-09-07T23:37:42+00:00" diff --git a/nselib/afp.lua b/nselib/afp.lua index f216d05e1..1bfa15daf 100644 --- a/nselib/afp.lua +++ b/nselib/afp.lua @@ -113,6 +113,7 @@ local bin = require "bin" local bit = require "bit" +local datetime = require "datetime" local ipOps = require "ipOps" local nmap = require "nmap" local os = require "os" @@ -1778,9 +1779,9 @@ Helper = { local item = ( response.result.file ) and response.result.file or response.result.dir local diff = os.time{year=2000, month=1, day=1, hour=0} - os.time{year=1970, month=1, day=1, hour=0} - local create = stdnse.format_timestamp(item.CreationDate + diff) - local backup = stdnse.format_timestamp(item.BackupDate ) - local modify = stdnse.format_timestamp(item.ModificationDate + diff ) + local create = datetime.format_timestamp(item.CreationDate + diff) + local backup = datetime.format_timestamp(item.BackupDate ) + local modify = datetime.format_timestamp(item.ModificationDate + diff ) return true, { create = create, backup = backup, modify = modify } end, diff --git a/nselib/datetime.lua b/nselib/datetime.lua index b93086a3b..509d74253 100644 --- a/nselib/datetime.lua +++ b/nselib/datetime.lua @@ -8,8 +8,19 @@ local stdnse = require "stdnse" local os = require "os" local math = require "math" +local string = require "string" _ENV = stdnse.module("datetime", stdnse.seeall) +local difftime = os.difftime +local time = os.time +local date = os.date + +local floor = math.floor +local fmod = math.fmod + +local format = string.format +local match = string.match + --- Record a time difference between the scanner and the target -- -- The skew will be recorded in the host's registry for later retrieval and @@ -24,10 +35,199 @@ function record_skew(host, timestamp, received) skew_tab = skew_tab or {} -- No srtt? I suppose we'll ignore it, but this could cause problems local srtt = host.times and host.times.srtt or 0 - local adjusted = os.difftime(math.floor(timestamp), math.floor(received)) - srtt / 2.0 + local adjusted = difftime(floor(timestamp), floor(received)) - srtt / 2.0 skew_tab[#skew_tab + 1] = adjusted stdnse.debug2("record_skew: %s", adjusted) host.registry.datetime_skew = skew_tab end +-- Find the offset in seconds between local time and UTC. That is, if we +-- interpret a UTC date table as a local date table by passing it to os.time, +-- how much must be added to the resulting integer timestamp to make it +-- correct? +local function utc_offset(t) + -- What does the calendar say locally? + local localtime = date("*t", t) + -- What does the calendar say in UTC? + local gmtime = date("!*t", t) + -- Interpret both as local calendar dates and find the difference. + return difftime(time(localtime), time(gmtime)) +end + +--- Convert a date table into an integer timestamp. +-- +-- Unlike os.time, this does not assume that the date table represents a local +-- time. Rather, it takes an optional offset number of seconds representing the +-- time zone, and returns the timestamp that would result using that time zone +-- as local time. If the offset is omitted or 0, the date table is interpreted +-- as a UTC date. For example, 4:00 UTC is the same as 5:00 UTC+1: +-- +-- date_to_timestamp({year=1970,month=1,day=1,hour=4,min=0,sec=0}) --> 14400 +-- date_to_timestamp({year=1970,month=1,day=1,hour=4,min=0,sec=0}, 0) --> 14400 +-- date_to_timestamp({year=1970,month=1,day=1,hour=5,min=0,sec=0}, 1*60*60) --> 14400 +-- +-- And 4:00 UTC+1 is an earlier time: +-- +-- date_to_timestamp({year=1970,month=1,day=1,hour=4,min=0,sec=0}, 1*60*60) --> 10800 +-- +function date_to_timestamp(date, offset) + offset = offset or 0 + return time(date) + utc_offset(time(date)) - offset +end + +local function format_tz(offset) + local sign, hh, mm + + if not offset then + return "" + end + if offset < 0 then + sign = "-" + offset = -offset + else + sign = "+" + end + -- Truncate to minutes. + offset = floor(offset / 60) + hh = floor(offset / 60) + mm = floor(fmod(offset, 60)) + + return format("%s%02d:%02d", sign, hh, mm) +end +--- Format a date and time (and optional time zone) for structured output. +-- +-- Formatting is done according to RFC 3339 (a profile of ISO 8601), except +-- that a time zone may be omitted to signify an unspecified local time zone. +-- Time zones are given as an integer number of seconds from UTC. Use +-- 0 to mark UTC itself. Formatted strings with a time zone look +-- like this: +-- +-- format_timestamp(os.time(), 0) --> "2012-09-07T23:37:42+00:00" +-- format_timestamp(os.time(), 2*60*60) --> "2012-09-07T23:37:42+02:00" +-- +-- Without a time zone they look like this: +-- +-- format_timestamp(os.time()) --> "2012-09-07T23:37:42" +-- +-- +-- This function should be used for all dates emitted as part of NSE structured +-- output. +function format_timestamp(t, offset) + if type(t) == "table" then + return format( + "%d-%02d-%02dT%02d:%02d:%02d", + t.year, t.month, t.day, t.hour, t.min, t.sec + ) + else + local tz_string = format_tz(offset) + offset = offset or 0 + local status, result = pcall(date, "!%Y-%m-%dT%H:%M:%S", floor(t + offset)) + if not status then + local tmp = floor(t + offset) + if tmp > 0xffffffff then + -- Maybe too far in the future? + local seconds_in_year = 31556926 + local extra_years = (tmp - 0xffffffff) // seconds_in_year + 1 + tmp = tmp - extra_years * seconds_in_year + status, result = pcall(date, "!*t", tmp) + if status then + -- seconds_in_year is imprecise, so we truncate to date only + result = format("%d-%02d-%02d", result.year + extra_years, result.month, result.day) + end + end + end + if not status then + return ("Invalid timestamp: %s"):format(t) + end + return result .. tz_string + end +end + +--- Format a time interval into a string +-- +-- String is in the same format as format_difftime +-- @param interval A time interval +-- @param unit The time unit division as a number. If interval is +-- in milliseconds, this is 1000 for instance. Default: 1 (seconds) +-- @return The time interval in string format +function format_time(interval, unit) + local sign = "" + if interval < 0 then + sign = "-" + interval = math.abs(interval) + end + unit = unit or 1 + local precision = floor(math.log(unit, 10)) + + local sec = (interval % (60 * unit)) / unit + interval = interval // (60 * unit) + local min = interval % 60 + interval = interval // 60 + local hr = interval % 24 + interval = interval // 24 + + local s = format("%.0fd%02.0fh%02.0fm%02.".. precision .."fs", + interval, hr, min, sec) + -- trim off leading 0 and "empty" units + return sign .. (match(s, "([1-9].*)") or format("%0.".. precision .."fs", 0)) +end + +--- Format the difference between times t2 and t1 +-- into a string +-- +-- String is in one of the forms (signs may vary): +-- * 0s +-- * -4s +-- * +2m38s +-- * -9h12m34s +-- * +5d17h05m06s +-- * -2y177d10h13m20s +-- The string shows t2 relative to t1; i.e., the +-- calculation is t2 minus t1. +function format_difftime(t2, t1) + local d, s, sign, yeardiff + + d = difftime(time(t2), time(t1)) + if d > 0 then + sign = "+" + elseif d < 0 then + sign = "-" + t2, t1 = t1, t2 + d = -d + else + sign = "" + end + -- t2 is always later than or equal to t1 here. + + -- The year is a tricky case because it's not a fixed number of days + -- the way a day is a fixed number of hours or an hour is a fixed + -- number of minutes. For example, the difference between 2008-02-10 + -- and 2009-02-10 is 366 days because 2008 was a leap year, but it + -- should be printed as 1y0d0h0m0s, not 1y1d0h0m0s. We advance t1 to be + -- the latest year such that it is still before t2, which means that its + -- year will be equal to or one less than t2's. The number of years + -- skipped is stored in yeardiff. + if t2.year > t1.year then + local tmpyear = t1.year + -- Put t1 in the same year as t2. + t1.year = t2.year + d = difftime(time(t2), time(t1)) + if d < 0 then + -- Too far. Back off one year. + t1.year = t2.year - 1 + d = difftime(time(t2), time(t1)) + end + yeardiff = t1.year - tmpyear + t1.year = tmpyear + else + yeardiff = 0 + end + + local s = format_time(d) + if yeardiff == 0 then return sign .. s end + -- Years. + s = format("%dy", yeardiff) .. s + return sign .. s +end + return _ENV diff --git a/nselib/dhcp.lua b/nselib/dhcp.lua index c89704628..575c508dc 100644 --- a/nselib/dhcp.lua +++ b/nselib/dhcp.lua @@ -15,6 +15,7 @@ -- o Added WPAD action local bin = require "bin" +local datetime = require "datetime" local ipOps = require "ipOps" local math = require "math" local nmap = require "nmap" @@ -226,7 +227,7 @@ local function read_time(data, pos, length) end pos, result = bin.unpack(">I", data, pos) - return pos, stdnse.format_time(result) + return pos, datetime.format_time(result) end ---Read a list of static routes. Each of them are a pair of IP addresses, a destination and a diff --git a/nselib/dhcp6.lua b/nselib/dhcp6.lua index 46f67cf1d..a3343572a 100644 --- a/nselib/dhcp6.lua +++ b/nselib/dhcp6.lua @@ -23,6 +23,7 @@ local bin = require "bin" local bit = require "bit" +local datetime = require "datetime" local ipOps = require "ipOps" local math = require "math" local nmap = require "nmap" @@ -523,7 +524,7 @@ OptionToString = { if ( HWTYPE_ETHER == opt.hwtype ) then local mac = stdnse.tohex(opt.mac):upper() mac = mac:gsub("..", "%1:"):sub(1, -2) - local tm = stdnse.format_timestamp(opt.time) + local tm = datetime.format_timestamp(opt.time) return "Client identifier", ("MAC: %s; Time: %s"):format(mac, tm) end end, diff --git a/nselib/ipp.lua b/nselib/ipp.lua index f1ea9ddfd..779cd7468 100644 --- a/nselib/ipp.lua +++ b/nselib/ipp.lua @@ -1,7 +1,7 @@ local bin = require "bin" +local datetime = require "datetime" local http = require "http" local nmap = require "nmap" -local os = require "os" local stdnse = require "stdnse" local tab = require "tab" local table = require "table" @@ -410,7 +410,7 @@ Helper = { results[printer] = results[printer] or {} table.insert(results[printer], { id = id, - time = stdnse.format_timestamp(tm), + time = datetime.format_timestamp(tm), state = ( IPP.StateName[tonumber(state)] or "Unknown" ), size = size, owner = owner, diff --git a/nselib/ldap.lua b/nselib/ldap.lua index e9d8bc942..7a39ceb53 100644 --- a/nselib/ldap.lua +++ b/nselib/ldap.lua @@ -19,6 +19,7 @@ -- local asn1 = require "asn1" +local datetime = require "datetime" local io = require "io" local nmap = require "nmap" local os = require "os" @@ -834,7 +835,7 @@ function convertADTimeStamp(timestamp) result = ( timestamp // 10000000 ) - 3036 result = result + base_time - result = stdnse.format_timestamp(result, 0) + result = datetime.format_timestamp(result, 0) else result = 'Never' end diff --git a/nselib/msrpc.lua b/nselib/msrpc.lua index 302370a67..75444a3d6 100644 --- a/nselib/msrpc.lua +++ b/nselib/msrpc.lua @@ -52,6 +52,7 @@ local bin = require "bin" local bit = require "bit" +local datetime = require "datetime" local ipOps = require "ipOps" local math = require "math" local msrpctypes = require "msrpctypes" @@ -1228,7 +1229,6 @@ function epmapper_lookup(smbstate,handle) netbios = nil, ncacn_http = nil } - --stdnse.set_tostring(lookup_response,stdnse.format_generator({key_order = {"new_handle,annotation,uuid,exe,tcp_port,udp_port,ip_addr,ncalrpc,ncacn_np,netbios,ncacn_http"}})) lookup_response.new_handle = string.sub(data,25,44) @@ -2629,7 +2629,7 @@ function winreg_enumkey(smbstate, handle, index, name) -- [in,out,unique] NTTIME *last_changed_time pos, result['changed_time'] = msrpctypes.unmarshall_NTTIME_ptr(arguments, pos) - result['changed_date'] = stdnse.format_timestamp(result['changed_time']) + result['changed_date'] = datetime.format_timestamp(result['changed_time']) pos, result['return'] = msrpctypes.unmarshall_int32(arguments, pos) if(result['return'] == nil) then @@ -2771,7 +2771,7 @@ function winreg_queryinfokey(smbstate, handle) -- [out,ref] NTTIME *last_changed_time pos, result['last_changed_time'] = msrpctypes.unmarshall_NTTIME(arguments, pos) - result['last_changed_date'] = stdnse.format_timestamp(result['last_changed_time']) + result['last_changed_date'] = datetime.format_timestamp(result['last_changed_time']) pos, result['return'] = msrpctypes.unmarshall_int32(arguments, pos) if(result['return'] == nil) then @@ -4421,7 +4421,7 @@ local function get_domain_info(host, domain) response['groups'] = groups response['users'] = names if(querydomaininfo2_result_8['info']['domain_create_time'] ~= 0) then - response['created'] = stdnse.format_timestamp(querydomaininfo2_result_8['info']['domain_create_time']) + response['created'] = datetime.format_timestamp(querydomaininfo2_result_8['info']['domain_create_time']) else response['created'] = "unknown" end @@ -4889,11 +4889,11 @@ function get_server_stats(host) local stats = netservergetstatistics_result['stat'] -- Convert the date to a string - stats['start_str'] = stdnse.format_timestamp(stats['start']) + stats['start_str'] = datetime.format_timestamp(stats['start']) -- Get the period and convert it to a proper time offset stats['period'] = os.time() - stats['start'] - stats.period_str = stdnse.format_time(stats.period) + stats.period_str = datetime.format_time(stats.period) -- Combine the 64-bit values stats['bytessent'] = bit.bor(bit.lshift(stats['bytessent_high'], 32), stats['bytessent_low']) diff --git a/nselib/natpmp.lua b/nselib/natpmp.lua index a0bcc3561..9222c33b2 100644 --- a/nselib/natpmp.lua +++ b/nselib/natpmp.lua @@ -7,6 +7,7 @@ -- @author Patrik Karlsson -- local bin = require "bin" +local datetime = require "datetime" local ipOps = require "ipOps" local nmap = require "nmap" local stdnse = require "stdnse" @@ -103,7 +104,7 @@ Response = { pos, self.time, self.ip = bin.unpack(">II", self.data, pos) self.ip = ipOps.fromdword(self.ip) - self.time = stdnse.format_timestamp(self.time) + self.time = datetime.format_timestamp(self.time) return true end, diff --git a/nselib/rpc.lua b/nselib/rpc.lua index 59896691e..f87b76199 100644 --- a/nselib/rpc.lua +++ b/nselib/rpc.lua @@ -77,6 +77,7 @@ local bin = require "bin" local datafiles = require "datafiles" +local datetime = require "datetime" local math = require "math" local nmap = require "nmap" local stdnse = require "stdnse" @@ -3204,7 +3205,7 @@ Util = -- @param number of seconds since some given start time -- (the "epoch") -- @return string that represents time. - TimeToString = stdnse.format_timestamp, + TimeToString = datetime.format_timestamp, --- Converts the size in bytes to a human readable format -- diff --git a/nselib/smb.lua b/nselib/smb.lua index be9f68241..4f6821e01 100644 --- a/nselib/smb.lua +++ b/nselib/smb.lua @@ -125,6 +125,7 @@ local asn1 = require "asn1" local bin = require "bin" local bit = require "bit" local coroutine = require "coroutine" +local datetime = require "datetime" local io = require "io" local math = require "math" local match = require "match" @@ -1049,7 +1050,7 @@ function negotiate_v1(smb, overrides) -- Convert the time and timezone to more useful values smb['time'] = (smb['time'] // 10000000) - 11644473600 - smb['date'] = stdnse.format_timestamp(smb['time']) + smb['date'] = datetime.format_timestamp(smb['time']) smb['timezone'] = -(smb['timezone'] / 60) if(smb['timezone'] == 0) then smb['timezone_str'] = "UTC+0" @@ -2861,7 +2862,7 @@ function find_files(smbstate, fname, options) local time = fe.created time = (time // 10000000) - 11644473600 - fe.created = stdnse.format_timestamp(time) + fe.created = datetime.format_timestamp(time) -- TODO: cleanup fe.s_fname pos, fe.fname = bin.unpack("A" .. f_len, response.data, pos) diff --git a/nselib/smb2.lua b/nselib/smb2.lua index 5a166efa5..12d525e5c 100644 --- a/nselib/smb2.lua +++ b/nselib/smb2.lua @@ -11,6 +11,7 @@ -- @copyright Same as Nmap--See https://nmap.org/book/man-legal.html --- +local datetime = require "datetime" local string = require "string" local stdnse = require "stdnse" local nmap = require "nmap" @@ -388,12 +389,12 @@ function negotiate_v2(smb, overrides) -- Convert the time and timezone to human readable values (taken from smb.lua) smb['time'] = (smb['time'] // 10000000) - 11644473600 - smb['date'] = stdnse.format_timestamp(smb['time']) + smb['date'] = datetime.format_timestamp(smb['time']) -- Samba does not report the boot time if smb['start_time'] ~= 0 then smb['start_time'] = (smb['start_time'] // 10000000) - 11644473600 - smb['start_date'] = stdnse.format_timestamp(smb['start_time']) + smb['start_date'] = datetime.format_timestamp(smb['start_time']) else smb['start_date'] = "N/A" end diff --git a/nselib/stdnse.lua b/nselib/stdnse.lua index fe9cf8462..7db8c9b5b 100644 --- a/nselib/stdnse.lua +++ b/nselib/stdnse.lua @@ -10,7 +10,6 @@ local _G = require "_G" local coroutine = require "coroutine" local math = require "math" local nmap = require "nmap" -local os = require "os" local string = require "string" local table = require "table" local assert = assert; @@ -30,8 +29,6 @@ local type = type local pcall = pcall local ceil = math.ceil -local floor = math.floor -local fmod = math.fmod local max = math.max local random = math.random @@ -50,10 +47,6 @@ local remove = table.remove; local pack = table.pack; local unpack = table.unpack; -local difftime = os.difftime; -local time = os.time; -local date = os.date; - local EMPTY = {}; -- Empty constant table _ENV = require "strict" {}; @@ -500,194 +493,6 @@ function parse_timespec(timespec) return t * m end --- Find the offset in seconds between local time and UTC. That is, if we --- interpret a UTC date table as a local date table by passing it to os.time, --- how much must be added to the resulting integer timestamp to make it --- correct? -local function utc_offset(t) - -- What does the calendar say locally? - local localtime = date("*t", t) - -- What does the calendar say in UTC? - local gmtime = date("!*t", t) - -- Interpret both as local calendar dates and find the difference. - return difftime(time(localtime), time(gmtime)) -end ---- Convert a date table into an integer timestamp. --- --- Unlike os.time, this does not assume that the date table represents a local --- time. Rather, it takes an optional offset number of seconds representing the --- time zone, and returns the timestamp that would result using that time zone --- as local time. If the offset is omitted or 0, the date table is interpreted --- as a UTC date. For example, 4:00 UTC is the same as 5:00 UTC+1: --- --- date_to_timestamp({year=1970,month=1,day=1,hour=4,min=0,sec=0}) --> 14400 --- date_to_timestamp({year=1970,month=1,day=1,hour=4,min=0,sec=0}, 0) --> 14400 --- date_to_timestamp({year=1970,month=1,day=1,hour=5,min=0,sec=0}, 1*60*60) --> 14400 --- --- And 4:00 UTC+1 is an earlier time: --- --- date_to_timestamp({year=1970,month=1,day=1,hour=4,min=0,sec=0}, 1*60*60) --> 10800 --- -function date_to_timestamp(date, offset) - offset = offset or 0 - return time(date) + utc_offset(time(date)) - offset -end - -local function format_tz(offset) - local sign, hh, mm - - if not offset then - return "" - end - if offset < 0 then - sign = "-" - offset = -offset - else - sign = "+" - end - -- Truncate to minutes. - offset = floor(offset / 60) - hh = floor(offset / 60) - mm = floor(fmod(offset, 60)) - - return format("%s%02d:%02d", sign, hh, mm) -end ---- Format a date and time (and optional time zone) for structured output. --- --- Formatting is done according to RFC 3339 (a profile of ISO 8601), except --- that a time zone may be omitted to signify an unspecified local time zone. --- Time zones are given as an integer number of seconds from UTC. Use --- 0 to mark UTC itself. Formatted strings with a time zone look --- like this: --- --- format_timestamp(os.time(), 0) --> "2012-09-07T23:37:42+00:00" --- format_timestamp(os.time(), 2*60*60) --> "2012-09-07T23:37:42+02:00" --- --- Without a time zone they look like this: --- --- format_timestamp(os.time()) --> "2012-09-07T23:37:42" --- --- --- This function should be used for all dates emitted as part of NSE structured --- output. -function format_timestamp(t, offset) - if type(t) == "table" then - return format( - "%d-%02d-%02dT%02d:%02d:%02d", - t.year, t.month, t.day, t.hour, t.min, t.sec - ) - else - local tz_string = format_tz(offset) - offset = offset or 0 - local status, result = pcall(date, "!%Y-%m-%dT%H:%M:%S", floor(t + offset)) - if not status then - local tmp = floor(t + offset) - if tmp > 0xffffffff then - -- Maybe too far in the future? - local seconds_in_year = 31556926 - local extra_years = (tmp - 0xffffffff) // seconds_in_year + 1 - tmp = tmp - extra_years * seconds_in_year - status, result = pcall(date, "!*t", tmp) - if status then - -- seconds_in_year is imprecise, so we truncate to date only - result = format("%d-%02d-%02d", result.year + extra_years, result.month, result.day) - end - end - end - if not status then - return ("Invalid timestamp: %s"):format(t) - end - return result .. tz_string - end -end - ---- Format a time interval into a string --- --- String is in the same format as format_difftime --- @param interval A time interval --- @param unit The time unit division as a number. If interval is --- in milliseconds, this is 1000 for instance. Default: 1 (seconds) --- @return The time interval in string format -function format_time(interval, unit) - local sign = "" - if interval < 0 then - sign = "-" - interval = math.abs(interval) - end - unit = unit or 1 - local precision = floor(math.log(unit, 10)) - - local sec = (interval % (60 * unit)) / unit - interval = interval // (60 * unit) - local min = interval % 60 - interval = interval // 60 - local hr = interval % 24 - interval = interval // 24 - - local s = format("%.0fd%02.0fh%02.0fm%02.".. precision .."fs", - interval, hr, min, sec) - -- trim off leading 0 and "empty" units - return sign .. (match(s, "([1-9].*)") or format("%0.".. precision .."fs", 0)) -end - ---- Format the difference between times t2 and t1 --- into a string --- --- String is in one of the forms (signs may vary): --- * 0s --- * -4s --- * +2m38s --- * -9h12m34s --- * +5d17h05m06s --- * -2y177d10h13m20s --- The string shows t2 relative to t1; i.e., the --- calculation is t2 minus t1. -function format_difftime(t2, t1) - local d, s, sign, yeardiff - - d = difftime(time(t2), time(t1)) - if d > 0 then - sign = "+" - elseif d < 0 then - sign = "-" - t2, t1 = t1, t2 - d = -d - else - sign = "" - end - -- t2 is always later than or equal to t1 here. - - -- The year is a tricky case because it's not a fixed number of days - -- the way a day is a fixed number of hours or an hour is a fixed - -- number of minutes. For example, the difference between 2008-02-10 - -- and 2009-02-10 is 366 days because 2008 was a leap year, but it - -- should be printed as 1y0d0h0m0s, not 1y1d0h0m0s. We advance t1 to be - -- the latest year such that it is still before t2, which means that its - -- year will be equal to or one less than t2's. The number of years - -- skipped is stored in yeardiff. - if t2.year > t1.year then - local tmpyear = t1.year - -- Put t1 in the same year as t2. - t1.year = t2.year - d = difftime(time(t2), time(t1)) - if d < 0 then - -- Too far. Back off one year. - t1.year = t2.year - 1 - d = difftime(time(t2), time(t1)) - end - yeardiff = t1.year - tmpyear - t1.year = tmpyear - else - yeardiff = 0 - end - - local s = format_time(d) - if yeardiff == 0 then return sign .. s end - -- Years. - s = format("%dy", yeardiff) .. s - return sign .. s -end - --- Returns the current time in milliseconds since the epoch -- @return The current time in milliseconds since the epoch function clock_ms() diff --git a/scripts/bitcoin-getaddr.nse b/scripts/bitcoin-getaddr.nse index 7788faa4d..a4d6d3f2f 100644 --- a/scripts/bitcoin-getaddr.nse +++ b/scripts/bitcoin-getaddr.nse @@ -1,4 +1,4 @@ -local os = require "os" +local datetime = require "datetime" local shortport = require "shortport" local stdnse = require "stdnse" local tab = require "tab" @@ -67,7 +67,7 @@ action = function(host, port) if ( target.ALLOW_NEW_TARGETS ) then target.add(node.address.host) end - tab.addrow(response, ("%s:%d"):format(node.address.host, node.address.port), stdnse.format_timestamp(node.ts)) + tab.addrow(response, ("%s:%d"):format(node.address.host, node.address.port), datetime.format_timestamp(node.ts)) end if ( #response > 1 ) then diff --git a/scripts/bitcoin-info.nse b/scripts/bitcoin-info.nse index b69349160..b31ac7fb2 100644 --- a/scripts/bitcoin-info.nse +++ b/scripts/bitcoin-info.nse @@ -63,7 +63,7 @@ action = function(host, port) datetime.record_skew(host, ver.timestamp, request_time) local result = stdnse.output_table() - result["Timestamp"] = stdnse.format_timestamp(ver.timestamp) + result["Timestamp"] = datetime.format_timestamp(ver.timestamp) result["Network"] = NETWORK[ver.magic] result["Version"] = ver.ver result["Node Id"] = ver.nodeid diff --git a/scripts/clock-skew.nse b/scripts/clock-skew.nse index 1b8140281..3344cc329 100644 --- a/scripts/clock-skew.nse +++ b/scripts/clock-skew.nse @@ -1,4 +1,5 @@ local coroutine = require "coroutine" +local datetime = require "datetime" local formulas = require "formulas" local math = require "math" local nmap = require "nmap" @@ -103,9 +104,9 @@ hostaction = function(host) if mean ~= 0 or stddev ~= 0 or nmap.verbosity() > 1 then local out = {mean = mean, stddev = stddev, median = median} return out, ("mean: %s, deviation: %s, median: %s"):format( - stdnse.format_time(mean), - stdnse.format_time(stddev), - stdnse.format_time(median) + datetime.format_time(mean), + datetime.format_time(stddev), + datetime.format_time(median) ) end end @@ -169,10 +170,10 @@ postaction = function() for mean, group in pairs(groups) do -- Collapse the biggest group if #groups > 1 and #group > host_count // 2 then - out[stdnse.format_time(mean)] = "Majority of systems scanned" + out[datetime.format_time(mean)] = "Majority of systems scanned" elseif #group > 1 then -- Only record groups of more than one system together - out[stdnse.format_time(mean)] = group + out[datetime.format_time(mean)] = group end end diff --git a/scripts/gkrellm-info.nse b/scripts/gkrellm-info.nse index 93c02eea6..d6dc3959c 100644 --- a/scripts/gkrellm-info.nse +++ b/scripts/gkrellm-info.nse @@ -1,3 +1,4 @@ +local datetime = require "datetime" local math = require "math" local match = require "match" local nmap = require "nmap" @@ -113,7 +114,7 @@ local function decodeTag(tag, lines) "version" == tag ) then return ("%s: %s"):format(long_names[tag], lines[1]) elseif ( "uptime" == tag ) then - return ("%s: %s"):format(long_names[tag], stdnse.format_time(lines[1] * 60)) + return ("%s: %s"):format(long_names[tag], datetime.format_time(lines[1] * 60)) elseif ( "mem" == tag ) then local total, used = table.unpack(stdnse.strsplit("%s", lines[1])) if ( not(total) or not(used) ) then diff --git a/scripts/gpsd-info.nse b/scripts/gpsd-info.nse index c7fc63075..b6aefaa6d 100644 --- a/scripts/gpsd-info.nse +++ b/scripts/gpsd-info.nse @@ -1,3 +1,4 @@ +local datetime = require "datetime" local gps = require "gps" local match = require "match" local nmap = require "nmap" @@ -96,7 +97,7 @@ action = function(host, port) end local output = { - ("Time of fix: %s"):format(stdnse.format_timestamp(gps.Util.convertTime(gpsinfo.date, gpsinfo.time))), + ("Time of fix: %s"):format(datetime.format_timestamp(gps.Util.convertTime(gpsinfo.date, gpsinfo.time))), ("Coordinates: %.4f,%.4f"):format(tonumber(gpsinfo.latitude), tonumber(gpsinfo.longitude)), ("Speed: %s knots"):format(gpsinfo.speed) } diff --git a/scripts/http-date.nse b/scripts/http-date.nse index 67eb04ac1..cea5d941d 100644 --- a/scripts/http-date.nse +++ b/scripts/http-date.nse @@ -1,3 +1,4 @@ +local datetime = require "datetime" local http = require "http" local os = require "os" local shortport = require "shortport" @@ -42,16 +43,16 @@ action = function(host, port) if not response_date then return end - local response_time = stdnse.date_to_timestamp(response_date) + local response_time = datetime.date_to_timestamp(response_date) local output_tab = stdnse.output_table() - output_tab.date = stdnse.format_timestamp(response_time, 0) + output_tab.date = datetime.format_timestamp(response_time, 0) output_tab.delta = os.difftime(response_time, request_time) datetime.record_skew(host, response_time, request_time) local output_str = string.format("%s; %s from local time.", - response.header["date"], stdnse.format_difftime(os.date("!*t", response_time), os.date("!*t", request_time))) + response.header["date"], datetime.format_difftime(os.date("!*t", response_time), os.date("!*t", request_time))) return output_tab, output_str end diff --git a/scripts/http-icloud-findmyiphone.nse b/scripts/http-icloud-findmyiphone.nse index b2bb71b36..beed63480 100644 --- a/scripts/http-icloud-findmyiphone.nse +++ b/scripts/http-icloud-findmyiphone.nse @@ -1,5 +1,5 @@ local mobileme = require "mobileme" -local os = require "os" +local datetime = require "datetime" local stdnse = require "stdnse" local tab = require "tab" @@ -74,7 +74,7 @@ action = function() end local ts if ( info.timestamp and 1000 < info.timestamp ) then - ts = stdnse.format_timestamp(info.timestamp//1000) + ts = datetime.format_timestamp(info.timestamp//1000) else ts = "-" end diff --git a/scripts/http-slowloris.nse b/scripts/http-slowloris.nse index 33d1102a3..87584e06b 100644 --- a/scripts/http-slowloris.nse +++ b/scripts/http-slowloris.nse @@ -1,4 +1,5 @@ local coroutine = require "coroutine" +local datetime = require "datetime" local math = require "math" local nmap = require "nmap" local os = require "os" @@ -334,7 +335,7 @@ action = function(host, port) end stop = os.date("!*t") - dos_time = stdnse.format_difftime(stop, start) + dos_time = datetime.format_difftime(stop, start) if DOSed then if Reason == "slowloris" then stdnse.debug2("Slowloris Attack stopped, building output") diff --git a/scripts/memcached-info.nse b/scripts/memcached-info.nse index 2d10c5ca0..a7168803a 100644 --- a/scripts/memcached-info.nse +++ b/scripts/memcached-info.nse @@ -57,7 +57,7 @@ local filter = { ["pid"] = { name = "Process ID" }, ["uptime"] = { name = "Uptime", func = function(v) return ("%d seconds"):format(v) end }, - ["time"] = { name = "Server time", func = stdnse.format_timestamp }, + ["time"] = { name = "Server time", func = datetime.format_timestamp }, ["pointer_size"] = { name = "Architecture", func = function(v) return v .. " bit" end }, ["rusage_user"] = { name = "Used CPU (user)" }, ["rusage_system"] = { name = "Used CPU (system)"}, diff --git a/scripts/ntp-info.nse b/scripts/ntp-info.nse index 01731bd30..06edaa257 100644 --- a/scripts/ntp-info.nse +++ b/scripts/ntp-info.nse @@ -112,7 +112,7 @@ action = function(host, port) datetime.record_skew(host, tstamp, recvtime) - output["receive time stamp"] = stdnse.format_timestamp(tstamp) + output["receive time stamp"] = datetime.format_timestamp(tstamp) end status, bufrlres = comm.exchange(host, port, rlreq, {timeout=TIMEOUT}) diff --git a/scripts/openlookup-info.nse b/scripts/openlookup-info.nse index aa20ec6ed..21d1bcc13 100644 --- a/scripts/openlookup-info.nse +++ b/scripts/openlookup-info.nse @@ -1,4 +1,5 @@ local comm = require "comm" +local datetime = require "datetime" local nmap = require "nmap" local shortport = require "shortport" local stdnse = require "stdnse" @@ -174,7 +175,7 @@ local function formattime(data) if not time then return end - return stdnse.format_timestamp(time) + return datetime.format_timestamp(time) end local function formatvalue(key, nson) diff --git a/scripts/openwebnet-discovery.nse b/scripts/openwebnet-discovery.nse index f8d78b236..274c8f808 100644 --- a/scripts/openwebnet-discovery.nse +++ b/scripts/openwebnet-discovery.nse @@ -1,3 +1,4 @@ +local datetime = require "datetime" local stdnse = require "stdnse" local shortport = require "shortport" local comm = require "comm" @@ -192,7 +193,7 @@ local function format_dimensions(res) values[ params[counter] ] = val end - res["Date and Time"] = stdnse.format_timestamp(values) + res["Date and Time"] = datetime.format_timestamp(values) end if res["Device Type"] then diff --git a/scripts/rfc868-time.nse b/scripts/rfc868-time.nse index 7b4636ec6..1b2b39f46 100644 --- a/scripts/rfc868-time.nse +++ b/scripts/rfc868-time.nse @@ -59,6 +59,6 @@ action = function(host, port) nmap.set_port_version(host, port, "hardmatched") end - return stdnse.format_timestamp(stamp) + return datetime.format_timestamp(stamp) end end diff --git a/scripts/rusers.nse b/scripts/rusers.nse index 11048e983..027b6c043 100644 --- a/scripts/rusers.nse +++ b/scripts/rusers.nse @@ -1,3 +1,4 @@ +local datetime = require "datetime" local rpc = require "rpc" local shortport = require "shortport" local stdnse = require "stdnse" @@ -108,10 +109,10 @@ local function rusers2_entry(comm, data, pos) if not pos then return fail(entry.host) end pos, entry.time = rpc.Util.unmarshall_uint32(data, pos) - entry.time = stdnse.format_timestamp(entry.time) + entry.time = datetime.format_timestamp(entry.time) pos, entry.idle = rpc.Util.unmarshall_uint32(data, pos) - entry.idle = stdnse.format_time(entry.idle) + entry.idle = datetime.format_time(entry.idle) return pos, entry, data end diff --git a/scripts/smb-enum-sessions.nse b/scripts/smb-enum-sessions.nse index 5aed00d3f..dd3725d4d 100644 --- a/scripts/smb-enum-sessions.nse +++ b/scripts/smb-enum-sessions.nse @@ -1,3 +1,4 @@ +local datetime = require "datetime" local msrpc = require "msrpc" local smb = require "smb" local stdnse = require "stdnse" @@ -306,14 +307,14 @@ action = function(host) if(time == 0) then time = "[just logged in, it's probably you]" else - time = stdnse.format_time(time) + time = datetime.format_time(time) end local idle_time = sessions[i]['idle_time'] if(idle_time == 0) then idle_time = "[not idle]" else - idle_time = stdnse.format_time(idle_time) + idle_time = datetime.format_time(idle_time) end table.insert(sessions_output, string.format("%s is connected from %s for %s, idle for %s", sessions[i]['user'], sessions[i]['client'], time, idle_time)) diff --git a/scripts/smb-os-discovery.nse b/scripts/smb-os-discovery.nse index c96df55f8..d15ad42c8 100644 --- a/scripts/smb-os-discovery.nse +++ b/scripts/smb-os-discovery.nse @@ -161,7 +161,7 @@ action = function(host) response.domain = result.domain response.server = result.server if result.time and result.timezone then - response.date = stdnse.format_timestamp(result.time, result.timezone * 60 * 60) + response.date = datetime.format_timestamp(result.time, result.timezone * 60 * 60) datetime.record_skew(host, result.time - result.timezone * 60 * 60, request_time) end response.fqdn = result.fqdn diff --git a/scripts/smb-system-info.nse b/scripts/smb-system-info.nse index bfdc6205f..7b761e829 100644 --- a/scripts/smb-system-info.nse +++ b/scripts/smb-system-info.nse @@ -1,3 +1,4 @@ +local datetime = require "datetime" local msrpc = require "msrpc" local os = require "os" local smb = require "smb" @@ -156,7 +157,7 @@ local function get_info_registry(host) result['status-currentversion'], result['currentversion'] = reg_get_value(smbstate, openhklm_result['handle'], "Software\\Microsoft\\Windows NT\\CurrentVersion", "CurrentVersion") result['status-installdate'], result['installdate'] = reg_get_value(smbstate, openhklm_result['handle'], "Software\\Microsoft\\Windows NT\\CurrentVersion", "InstallDate") if(result['status-installdate'] ~= false) then - result['installdate'] = stdnse.format_timestamp(result['installdate']) + result['installdate'] = datetime.format_timestamp(result['installdate']) end result['status-productname'], result['productname'] = reg_get_value(smbstate, openhklm_result['handle'], "Software\\Microsoft\\Windows NT\\CurrentVersion", "Productname") diff --git a/scripts/snmp-info.nse b/scripts/snmp-info.nse index 227ee509c..bad3f4f24 100644 --- a/scripts/snmp-info.nse +++ b/scripts/snmp-info.nse @@ -1,3 +1,4 @@ +local datetime = require "datetime" local datafiles = require "datafiles" local ipOps = require "ipOps" local nmap = require "nmap" @@ -129,7 +130,7 @@ action = function (host, port) output.engineIDData = stdnse.tohex(engineID:sub(5)) end output.snmpEngineBoots = decoded[2] - output.snmpEngineTime = stdnse.format_time(decoded[3]) + output.snmpEngineTime = datetime.format_time(decoded[3]) port.version = port.version or {} port.version.service = "snmp" diff --git a/scripts/snmp-sysdescr.nse b/scripts/snmp-sysdescr.nse index 3c8cb2e55..30fa84565 100644 --- a/scripts/snmp-sysdescr.nse +++ b/scripts/snmp-sysdescr.nse @@ -1,3 +1,4 @@ +local datetime = require "datetime" local nmap = require "nmap" local shortport = require "shortport" local snmp = require "snmp" @@ -62,7 +63,7 @@ action = function(host, port) return end - result = result .. "\n" .. string.format(" System uptime: %s (%s timeticks)", stdnse.format_time(uptime, 100), tostring(uptime)) + result = result .. "\n" .. string.format(" System uptime: %s (%s timeticks)", datetime.format_time(uptime, 100), tostring(uptime)) return result end diff --git a/scripts/snmp-win32-software.nse b/scripts/snmp-win32-software.nse index 64d0100e0..f7ed99271 100644 --- a/scripts/snmp-win32-software.nse +++ b/scripts/snmp-win32-software.nse @@ -1,3 +1,4 @@ +local datetime = require "datetime" local bin = require "bin" local nmap = require "nmap" local shortport = require "shortport" @@ -90,7 +91,7 @@ local date_xlate = { sec = 7 } --- translate date parts to positional indices for stdnse.format_timestamp +-- translate date parts to positional indices for datetime.format_timestamp local date_metatab = { __index = function (t, k) return t[date_xlate[k]] @@ -123,7 +124,7 @@ local function process_answer( tbl ) local sw_item = { ["name"] = v.value, - ["install_date"] = stdnse.format_timestamp(install_date_tab) + ["install_date"] = datetime.format_timestamp(install_date_tab) } setmetatable(sw_item, sw_metatab) diff --git a/scripts/ssl-cert.nse b/scripts/ssl-cert.nse index 62d0b08af..6fe3d4db8 100644 --- a/scripts/ssl-cert.nse +++ b/scripts/ssl-cert.nse @@ -1,3 +1,4 @@ +local datetime = require "datetime" local nmap = require "nmap" local shortport = require "shortport" local sslcert = require "sslcert" @@ -143,7 +144,7 @@ function date_to_string(date) if type(date) == "string" then return string.format("Can't parse; string is \"%s\"", date) else - return stdnse.format_timestamp(date) + return datetime.format_timestamp(date) end end @@ -218,7 +219,7 @@ local function output_tab(cert) if type(v)=="string" then o.validity[k] = v else - o.validity[k] = stdnse.format_timestamp(v) + o.validity[k] = datetime.format_timestamp(v) end end o.md5 = stdnse.tohex(cert:digest("md5")) diff --git a/scripts/ssl-date.nse b/scripts/ssl-date.nse index db48470e7..83e208a3e 100644 --- a/scripts/ssl-date.nse +++ b/scripts/ssl-date.nse @@ -140,7 +140,7 @@ local get_time_sample = function (host, port) -- extract time from response local tstatus, ttm = extract_time(response) if not tstatus then return nil end - stdnse.debug(detail_debug, "TLS sample: %s", stdnse.format_timestamp(ttm, 0)) + stdnse.debug(detail_debug, "TLS sample: %s", datetime.format_timestamp(ttm, 0)) return {target=ttm, scanner=stm, delta=os.difftime(ttm, stm)} end @@ -205,11 +205,11 @@ action = function(host, port) datetime.record_skew(host, tm.target, tm.scanner) local output = { - date = stdnse.format_timestamp(tm.target, 0), + date = datetime.format_timestamp(tm.target, 0), delta = tm.delta, } return output, string.format("%s; %s from scanner time.", output.date, - stdnse.format_difftime(os.date("!*t", tm.target), + datetime.format_difftime(os.date("!*t", tm.target), os.date("!*t", tm.scanner))) end