| 788 | } |
| 789 | |
| 790 | func (auth *AuthService) lockdownMode() { |
| 791 | ctx, cancel := context.WithCancel(context.Background()) |
| 792 | defer cancel() |
| 793 | auth.lockdownCtx = ctx |
| 794 | auth.lockdownCancelFunc = cancel |
| 795 | |
| 796 | auth.loginMutex.Lock() |
| 797 | |
| 798 | tlog.App.Warn().Msg("Multiple login attempts detected, possibly DDOS attack. Activating temporary lockdown.") |
| 799 | |
| 800 | auth.lockdown = &Lockdown{ |
| 801 | Active: true, |
| 802 | ActiveUntil: time.Now().Add(time.Duration(auth.config.LoginTimeout) * time.Second), |
| 803 | } |
| 804 | |
| 805 | // At this point all login attemps will also expire so, |
| 806 | // we might as well clear them to free up memory |
| 807 | auth.loginAttempts = make(map[string]*LoginAttempt) |
| 808 | |
| 809 | timer := time.NewTimer(time.Until(auth.lockdown.ActiveUntil)) |
| 810 | defer timer.Stop() |
| 811 | |
| 812 | auth.loginMutex.Unlock() |
| 813 | |
| 814 | select { |
| 815 | case <-timer.C: |
| 816 | // Timer expired, end lockdown |
| 817 | case <-ctx.Done(): |
| 818 | // Context cancelled, end lockdown |
| 819 | } |
| 820 | |
| 821 | auth.loginMutex.Lock() |
| 822 | |
| 823 | tlog.App.Info().Msg("Lockdown period ended, resuming normal operation") |
| 824 | auth.lockdown = nil |
| 825 | auth.loginMutex.Unlock() |
| 826 | } |
| 827 | |
| 828 | // Function only used for testing - do not use in prod! |
| 829 | func (auth *AuthService) ClearRateLimitsTestingOnly() { |