diff --git a/nselib/datetime.lua b/nselib/datetime.lua index 509d74253..a3cbf8677 100644 --- a/nselib/datetime.lua +++ b/nselib/datetime.lua @@ -41,6 +41,12 @@ function record_skew(host, timestamp, received) host.registry.datetime_skew = skew_tab end +-- Work around Windows error formatting time zones where 1970/1/1 UTC was 1969/12/31 +system_time_at_epoch = ( + time({year=1970, month=1, day=2, hour=0}) -- local time on 1970/1/2 + - 86400 -- minus 1 day = local time at 1970/1/1 + - time(date("!*t", 0)) -- minus UTC offset (Windows). On *nix this is 0. + ) -- 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 @@ -70,9 +76,14 @@ end -- -- 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) +function date_to_timestamp(date_t, offset) + local status, tm = pcall(time, date_t) + if not status then + stdnse.debug1("Invalid date for this platform: %s", tm) + return nil + end offset = offset or 0 - return time(date) + utc_offset(time(date)) - offset + return tm + utc_offset(tm) - offset end local function format_tz(offset) @@ -124,15 +135,21 @@ function format_timestamp(t, offset) local status, result = pcall(date, "!%Y-%m-%dT%H:%M:%S", floor(t + offset)) if not status then local tmp = floor(t + offset) + local extra_years + local seconds_in_year = 31556926 if tmp > 0xffffffff then -- Maybe too far in the future? - local seconds_in_year = 31556926 - local extra_years = (tmp - 0xffffffff) // seconds_in_year + 1 + extra_years = (tmp - 0xffffffff) // seconds_in_year + 1 + elseif tmp < system_time_at_epoch then + -- Windows can't display times before the epoch + extra_years = tmp // seconds_in_year + end + if extra_years then 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) + result = format("%d-%02d-%02d?", result.year + extra_years, result.month, result.day) end end end diff --git a/nselib/ldap.lua b/nselib/ldap.lua index 8d46757b2..34eb67da9 100644 --- a/nselib/ldap.lua +++ b/nselib/ldap.lua @@ -824,7 +824,9 @@ end function convertADTimeStamp(timestamp) local result = 0 - local base_time = tonumber(os.time({year=1601, month=1, day=1, hour=0, minute=0, sec =0})) + -- Windows cannot represent this time, so we pre-calculated it: + -- os.time({year=1601, month=1, day=1, hour=0, minute=0, sec =0}) + local base_time = -11644473600 timestamp = tonumber(timestamp) diff --git a/nselib/mssql.lua b/nselib/mssql.lua index f8e22b0df..d5bb155c5 100644 --- a/nselib/mssql.lua +++ b/nselib/mssql.lua @@ -106,7 +106,7 @@ local math = require "math" local match = require "match" local nmap = require "nmap" -local os = require "os" +local datetime = require "datetime" local shortport = require "shortport" local smb = require "smb" local smbauth = require "smbauth" @@ -156,6 +156,8 @@ do end end +-- This constant is number of seconds from 1900-01-01 to 1970-01-01 +local tds_offset_seconds = -2208988800 + datetime.system_time_at_epoch -- ************************************* -- Informational Classes @@ -1231,19 +1233,13 @@ ColumnData = end, [DataTypes.SYBDATETIME] = function( data, pos ) - local hi, lo, result_seconds, result - local tds_epoch, system_epoch, tds_offset_seconds + local hi, lo hi, lo, pos = string.unpack("