From 65f346499594c1a3fe63fba065d01f7534a00d62 Mon Sep 17 00:00:00 2001 From: Margo Crawford Date: Tue, 7 Dec 2021 16:57:39 -0800 Subject: [PATCH] Fix issue with very high integer value parsing, add unit tests also add comment about urgent replication --- internal/upstreamldap/upstreamldap.go | 6 +++--- internal/upstreamldap/upstreamldap_test.go | 10 ++++++++++ test/integration/supervisor_login_test.go | 7 ++++++- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/internal/upstreamldap/upstreamldap.go b/internal/upstreamldap/upstreamldap.go index 9030de81..781d9f5e 100644 --- a/internal/upstreamldap/upstreamldap.go +++ b/internal/upstreamldap/upstreamldap.go @@ -896,13 +896,13 @@ func win32timestampToTime(win32timestamp string) (time.Time, error) { const unixTimeBaseAsWin = 116_444_736_000_000_000 // The unix base time (January 1, 1970 UTC) as 100 ns since Win32 epoch (1601-01-01) const hundredNsToSecFactor = 10_000_000 - win32Time, err := strconv.ParseUint(win32timestamp, 10, 64) + win32Time, err := strconv.ParseInt(win32timestamp, 10, 64) if err != nil { return time.Time{}, fmt.Errorf("couldn't parse as timestamp") } - unixsec := int64(win32Time-unixTimeBaseAsWin) / hundredNsToSecFactor - unixns := int64(win32Time%hundredNsToSecFactor) * 100 + unixsec := (win32Time - unixTimeBaseAsWin) / hundredNsToSecFactor + unixns := (win32Time % hundredNsToSecFactor) * 100 convertedTime := time.Unix(unixsec, unixns).UTC() return convertedTime, nil diff --git a/internal/upstreamldap/upstreamldap_test.go b/internal/upstreamldap/upstreamldap_test.go index b2619baf..9b573b9c 100644 --- a/internal/upstreamldap/upstreamldap_test.go +++ b/internal/upstreamldap/upstreamldap_test.go @@ -2085,6 +2085,16 @@ func TestWin32TimestampToTime(t *testing.T) { timestampString: "132540199410000001", wantTime: time.Date(2021, time.January, 2, 0, 12, 21, 100, time.UTC).UTC(), }, + { + name: "max allowable value", + timestampString: "9223372036854775807", // 2^63-1 + wantTime: time.Date(30828, time.September, 14, 2, 48, 5, 477580700, time.UTC).UTC(), + }, + { + name: "just past max allowable value", + timestampString: "9223372036854775808", // 2^63 + wantErr: "couldn't parse as timestamp", + }, } for _, test := range tests { diff --git a/test/integration/supervisor_login_test.go b/test/integration/supervisor_login_test.go index 9f54d543..812a32b9 100644 --- a/test/integration/supervisor_login_test.go +++ b/test/integration/supervisor_login_test.go @@ -1879,7 +1879,12 @@ func lockADTestUser(t *testing.T, env *testlib.TestEnv, testUserName string) { userDN := fmt.Sprintf("CN=%s,OU=test-users,%s", testUserName, env.SupervisorUpstreamActiveDirectory.UserSearchBase) conn := dialTLS(t, env) - for i := 0; i <= 21; i++ { // our password policy allows 20 wrong attempts before locking the account, so do 21. + // our password policy allows 20 wrong attempts before locking the account, so do 21. + // these wrong password attempts could go to different domain controllers, but account + // lockout changes are urgently replicated, meaning that the domain controllers will be + // synced asap rather than in the usual 15 second interval. + // See https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-2000-server/cc961787(v=technet.10)#urgent-replication-of-account-lockout-changes + for i := 0; i <= 21; i++ { err := conn.Bind(userDN, "not-the-right-password-"+fmt.Sprint(i)) require.Error(t, err) // this should be an error }