Skip to content

Commit

Permalink
Feat: Add account name handling to feature requests and brute force
Browse files Browse the repository at this point in the history
This commit introduces code to retrieve and use the account name in various parts of the server logic, including feature requests and brute force protection. Additionally, it adds a constant for a meta user account key and ensures account-related fields are populated when available.

Signed-off-by: Christian Roessner <[email protected]>
  • Loading branch information
Christian Roessner committed Nov 11, 2024
1 parent 2f54f28 commit e451605
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 57 deletions.
92 changes: 41 additions & 51 deletions server/core/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -1132,6 +1132,7 @@ func (a *AuthState) handleFeatures(ctx *gin.Context) (authResult global.AuthResu
}

finished := make(chan action.Done)
accountName := a.getAccount()

action.RequestChan <- &action.Action{
LuaAction: luaAction,
Expand All @@ -1141,7 +1142,7 @@ func (a *AuthState) handleFeatures(ctx *gin.Context) (authResult global.AuthResu
CommonRequest: &lualib.CommonRequest{
Debug: config.LoadableConfig.Server.Log.Level.Level() == global.LogLevelDebug,
Repeating: false,
UserFound: false, // unavailable
UserFound: func() bool { return accountName != "" }(),
Authenticated: false, // unavailable
NoAuth: a.NoAuth,
BruteForceCounter: 0, // unavailable
Expand All @@ -1156,8 +1157,8 @@ func (a *AuthState) handleFeatures(ctx *gin.Context) (authResult global.AuthResu
LocalPort: a.XPort,
UserAgent: *a.UserAgent,
Username: a.Username,
Account: "", // unavailable
AccountField: "", // unavailable
Account: accountName,
AccountField: a.getAccountField(),
UniqueUserID: "", // unavailable
DisplayName: "", // unavailable
Password: a.Password,
Expand Down Expand Up @@ -1273,37 +1274,32 @@ func (a *AuthState) postLuaAction(passDBResult *PassDBResult) {
}

finished := make(chan action.Done)
accountName := a.getAccount()

action.RequestChan <- &action.Action{
LuaAction: global.LuaActionPost,
Context: a.Context,
FinishedChan: finished,
HTTPRequest: a.HTTPClientContext.Request,
CommonRequest: &lualib.CommonRequest{
Debug: config.LoadableConfig.Server.Log.Level.Level() == global.LogLevelDebug,
Repeating: false,
UserFound: passDBResult.UserFound,
Authenticated: passDBResult.Authenticated,
NoAuth: a.NoAuth,
BruteForceCounter: 0,
Service: a.Service,
Session: *a.GUID,
ClientIP: a.ClientIP,
ClientPort: a.XClientPort,
ClientNet: "", // unavailable
ClientHost: a.ClientHost,
ClientID: a.XClientID,
LocalIP: a.XLocalIP,
LocalPort: a.XPort,
UserAgent: *a.UserAgent,
Username: a.Username,
Account: func() string {
if passDBResult.UserFound {
return a.getAccount()
}

return ""
}(),
Debug: config.LoadableConfig.Server.Log.Level.Level() == global.LogLevelDebug,
Repeating: false,
UserFound: func() bool { return passDBResult.UserFound || accountName != "" }(),
Authenticated: passDBResult.Authenticated,
NoAuth: a.NoAuth,
BruteForceCounter: 0,
Service: a.Service,
Session: *a.GUID,
ClientIP: a.ClientIP,
ClientPort: a.XClientPort,
ClientNet: "", // unavailable
ClientHost: a.ClientHost,
ClientID: a.XClientID,
LocalIP: a.XLocalIP,
LocalPort: a.XPort,
UserAgent: *a.UserAgent,
Username: a.Username,
Account: accountName,
AccountField: a.getAccountField(),
UniqueUserID: a.getUniqueUserID(),
DisplayName: a.getDisplayName(),
Expand Down Expand Up @@ -1664,30 +1660,24 @@ func (a *AuthState) filterLua(passDBResult *PassDBResult, ctx *gin.Context) glob
Logs: nil,
Context: a.Context,
CommonRequest: &lualib.CommonRequest{
Debug: config.LoadableConfig.Server.Log.Level.Level() == global.LogLevelDebug,
Repeating: false, // unavailable
UserFound: passDBResult.UserFound,
Authenticated: passDBResult.Authenticated,
NoAuth: a.NoAuth,
BruteForceCounter: 0, // unavailable
Service: a.Service,
Session: *a.GUID,
ClientIP: a.ClientIP,
ClientPort: a.XClientPort,
ClientNet: "", // unavailable
ClientHost: a.ClientHost,
ClientID: a.XClientID,
UserAgent: *a.UserAgent,
LocalIP: a.XLocalIP,
LocalPort: a.XPort,
Username: a.Username,
Account: func() string {
if passDBResult.UserFound {
return a.getAccount()
}

return ""
}(),
Debug: config.LoadableConfig.Server.Log.Level.Level() == global.LogLevelDebug,
Repeating: false, // unavailable
UserFound: passDBResult.UserFound,
Authenticated: passDBResult.Authenticated,
NoAuth: a.NoAuth,
BruteForceCounter: 0, // unavailable
Service: a.Service,
Session: *a.GUID,
ClientIP: a.ClientIP,
ClientPort: a.XClientPort,
ClientNet: "", // unavailable
ClientHost: a.ClientHost,
ClientID: a.XClientID,
UserAgent: *a.UserAgent,
LocalIP: a.XLocalIP,
LocalPort: a.XPort,
Username: a.Username,
Account: a.getAccount(),
AccountField: a.getAccountField(),
UniqueUserID: a.getUniqueUserID(),
DisplayName: a.getDisplayName(),
Expand Down
17 changes: 14 additions & 3 deletions server/core/bruteforce.go
Original file line number Diff line number Diff line change
Expand Up @@ -681,6 +681,14 @@ func (a *AuthState) processBlockedAccount() {
return
}

if a.AccountField == nil && a.Attributes == nil {
accountField := global.MetaUserAccount
attributes := make(backend.DatabaseResult)

a.AccountField = &accountField
attributes[global.MetaUserAccount] = []any{accountName}
}

key := config.LoadableConfig.Server.Redis.Prefix + global.RedisBlockedAccountsKey

if err := rediscli.ReadHandle.SIsMember(a.HTTPClientContext, key, accountName).Err(); err != nil {
Expand All @@ -698,6 +706,8 @@ func (a *AuthState) processBlockedAccount() {
}

stats.RedisWriteCounter.Inc()

return
}

// getUserAccountFromCache fetches the user account name from Redis cache using the provided username.
Expand Down Expand Up @@ -805,6 +815,7 @@ func (a *AuthState) checkBucketOverLimit(rules []config.BruteForceRule, network
func (a *AuthState) handleBruteForceLuaAction(alreadyTriggered bool, rule *config.BruteForceRule, network *net.IPNet) {
if config.LoadableConfig.HaveLuaActions() {
finished := make(chan action.Done)
accountName := a.getAccount()

action.RequestChan <- &action.Action{
LuaAction: global.LuaActionBruteForce,
Expand All @@ -814,7 +825,7 @@ func (a *AuthState) handleBruteForceLuaAction(alreadyTriggered bool, rule *confi
CommonRequest: &lualib.CommonRequest{
Debug: config.LoadableConfig.Server.Log.Level.Level() == global.LogLevelDebug,
Repeating: alreadyTriggered,
UserFound: false, // unavailable
UserFound: func() bool { return accountName != "" }(),
Authenticated: false, // unavailable
NoAuth: a.NoAuth,
BruteForceCounter: a.BruteForceCounter[rule.Name],
Expand All @@ -829,8 +840,8 @@ func (a *AuthState) handleBruteForceLuaAction(alreadyTriggered bool, rule *confi
LocalPort: a.XPort,
UserAgent: *a.UserAgent,
Username: a.Username,
Account: "", // unavailable
AccountField: "", // unavailable
Account: accountName,
AccountField: a.getAccountField(),
UniqueUserID: "", // unavailable
DisplayName: "", // unavailable
Password: a.Password,
Expand Down
8 changes: 5 additions & 3 deletions server/core/features.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,12 +99,14 @@ func (a *AuthState) featureLua(ctx *gin.Context) (triggered bool, abortFeatures
defer stopTimer()
}

accountName := a.getAccount()

featureRequest := feature.Request{
Context: a.Context,
CommonRequest: &lualib.CommonRequest{
Debug: config.LoadableConfig.Server.Log.Level.Level() == global.LogLevelDebug,
Repeating: false, // unavailable
UserFound: false, // unavailable
UserFound: func() bool { return accountName != "" }(),
Authenticated: false, // unavailable
NoAuth: a.NoAuth,
BruteForceCounter: 0, // unavailable
Expand All @@ -119,8 +121,8 @@ func (a *AuthState) featureLua(ctx *gin.Context) (triggered bool, abortFeatures
LocalIP: a.XLocalIP,
LocalPort: a.XPort,
Username: a.Username,
Account: "", // unavailable
AccountField: "", // unavailable
Account: accountName,
AccountField: a.getAccountField(),
UniqueUserID: "", // unavailable
DisplayName: "", // unavailable
Password: a.Password,
Expand Down
5 changes: 5 additions & 0 deletions server/global/const.go
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,11 @@ const (
MaxPasswordHistoryEntries = 100
)

const (
// MetaUserAccount is a constant string used as a meta key for referencing a user account in various contexts.
MetaUserAccount = "__nauthilus_meta_user_account__"
)

// Log level.
const (
// LogLevelNone is the iota constant representing no logs
Expand Down

0 comments on commit e451605

Please sign in to comment.