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("