func newThrottle(cliffLen int32, thrTimeSec time.Duration, autoUnblockSec time.Duration, hotpWindowSize time.Duration, totpWindowSize time.Duration) throtteling {
	return throtteling{
		cliffLen,
		thrTimeSec,
		defs.GetBeginningOfTime(),
		defs.GetBeginningOfTime(),
		hotpWindowSize,
		defaultConsErrorCounter,
		autoUnblockSec,
		defs.GetBeginningOfTime(),
		totpWindowSize,
		"",
	}
}
func (u *UserInfoOtp) handleOkCode(code string, otpType TypeOfOtp, offset int32) (bool, error) {
	if otpType == HotpType && offset != 0 {
		u.BaseHotp.Count += int64(offset) // resync the provider interal counter to the client counter
		// TODO log
	}
	if otpType == HotpType {
		u.Throttle.throttlingTimerHotp = defs.GetBeginningOfTime()
		u.BaseHotp.Next()
	} else { // you can't try the code till the next Totp period
		u.Throttle.throttlingTimerTotp = defs.GetBeginningOfTime()
		u.Throttle.lastTotpCode = code
	}
	u.Throttle.consErrorCounter = defaultConsErrorCounter // clear the consecutive error counter
	return true, nil
}
// Verify that the given password is the expected one and that it is not expired
// If the overrideChecks is set, do not check the errorCounter and expiration, it uses for passwordUpdate
func (u *UserPwd) isPasswordMatchHandler(pwd []byte, overrideChecks bool) error {
	p1Lock.Lock()
	defer p1Lock.Unlock()

	if overrideChecks == false {
		if u.ErrorsCounter >= maxPwdAttempts {
			compareHashedPwd(pwd, u.Password) // against timing attacks
			return fmt.Errorf("Too many password attempts. You must reset password before trying again.")
		}
		err := isPwdLengthValid(pwd)
		if err != nil {
			return err
		}
		if compareHashedPwd(pwd, u.Password) == false {
			u.ErrorsCounter = u.ErrorsCounter + 1
			return fmt.Errorf("Password is wrong, please try again")
		} // don't check it again
		// Check expiration only for valid password: to hide the information that the user is valid
		if time.Now().After(u.Expiration) {
			return fmt.Errorf("Password has expired, please replace it")
		}
	}
	// the error counter must be increased also for password update to avoid backdoors
	if overrideChecks != false && compareHashedPwd(pwd, u.Password) == false {
		u.ErrorsCounter = u.ErrorsCounter + 1
		return fmt.Errorf("Password is wrong, please try again")
	}
	if u.TemporaryPwd == true {
		u.Expiration = defs.GetBeginningOfTime() // old use time.Now()              // The password expired => it can't be used any more.
		u.SetTemporaryPwd(defaultTemporaryPwd)   // Reset to the default option for the next password
	}
	u.ErrorsCounter = 0
	return nil
}