|
@@ -0,0 +1,51 @@
|
|
|
+package explogin
|
|
|
+
|
|
|
+import (
|
|
|
+ "math"
|
|
|
+ "sync"
|
|
|
+)
|
|
|
+
|
|
|
+/*
|
|
|
+ Explogin.go
|
|
|
+ Package to handle expotential login time
|
|
|
+ so as to prevent someone from brute forcing your password
|
|
|
+
|
|
|
+ Author: tobychui
|
|
|
+*/
|
|
|
+
|
|
|
+type UserLoginEntry struct {
|
|
|
+ Username string
|
|
|
+ TargetIP string
|
|
|
+ Timestamp int64
|
|
|
+ RetryCount int64
|
|
|
+}
|
|
|
+
|
|
|
+type ExpLoginHandler struct {
|
|
|
+ LoginRecord *sync.Map //Sync map to store UserLoginEntry, username+ip as key
|
|
|
+ BaseDelay int //Base delay exponent
|
|
|
+ DelayCeiling int //Max delay time
|
|
|
+}
|
|
|
+
|
|
|
+//Create a new exponential login handler object
|
|
|
+func NewExponentialLoginHandler(baseDelay int) *ExpLoginHandler {
|
|
|
+ recordMap := sync.Map{}
|
|
|
+
|
|
|
+ return &ExpLoginHandler{
|
|
|
+ LoginRecord: &recordMap,
|
|
|
+ BaseDelay: baseDelay,
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+//Check allow access now, if false return how many seconds till next retry
|
|
|
+func (e *ExpLoginHandler) AllowImmediateAccess(username string, ip string) (bool, int64) {
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+func (e *ExpLoginHandler) getDelayTimeFromRetryCount(retryCount int) int64 {
|
|
|
+ delaySecs := int64(math.Floor((math.Pow(2, float64(retryCount)) - 1) * 0.5))
|
|
|
+ if delaySecs > int64(e.DelayCeiling) {
|
|
|
+ delaySecs = int64(e.DelayCeiling)
|
|
|
+ }
|
|
|
+
|
|
|
+ return delaySecs
|
|
|
+}
|