Build 14
- implemented address datatype for rulesets - added more helper functions for use by rulesets - fixed missing syntax checks in ruleset parser - developed and integrated AuthWatchdog class - added meta-variables for stateful login filtering
This commit is contained in:
parent
3f38fcecd0
commit
c74b12183f
@ -1,4 +1,4 @@
|
|||||||
Auth Redux Mod v2.8b
|
Auth Redux Mod v2.9b
|
||||||
By Leslie Krause
|
By Leslie Krause
|
||||||
|
|
||||||
Auth Redux is a drop-in replacement for the builtin authentication handler of Minetest.
|
Auth Redux is a drop-in replacement for the builtin authentication handler of Minetest.
|
||||||
@ -88,6 +88,13 @@ Version 2.8b (24-Jul-2018)
|
|||||||
- updated comparison algorithm in ruleset parser
|
- updated comparison algorithm in ruleset parser
|
||||||
- passed preset variables array to filter functions
|
- passed preset variables array to filter functions
|
||||||
|
|
||||||
|
Version 2.9b (26-Jul-2018)
|
||||||
|
- implemented address datatype for rulesets
|
||||||
|
- added more helper functions for use by rulesets
|
||||||
|
- fixed missing syntax checks in ruleset parser
|
||||||
|
- developed and integrated AuthWatchdog class
|
||||||
|
- added meta-variables for stateful login filtering
|
||||||
|
|
||||||
Installation
|
Installation
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
|
42
filter.lua
42
filter.lua
@ -1,12 +1,13 @@
|
|||||||
--------------------------------------------------------
|
--------------------------------------------------------
|
||||||
-- Minetest :: Auth Redux Mod v2.8 (auth_rx)
|
-- Minetest :: Auth Redux Mod v2.9 (auth_rx)
|
||||||
--
|
--
|
||||||
-- See README.txt for licensing and release notes.
|
-- See README.txt for licensing and release notes.
|
||||||
-- Copyright (c) 2017-2018, Leslie E. Krause
|
-- Copyright (c) 2017-2018, Leslie E. Krause
|
||||||
--------------------------------------------------------
|
--------------------------------------------------------
|
||||||
|
|
||||||
FILTER_TYPE_STRING = 11
|
FILTER_TYPE_STRING = 10
|
||||||
FILTER_TYPE_NUMBER = 12
|
FILTER_TYPE_NUMBER = 11
|
||||||
|
FILTER_TYPE_ADDRESS = 12
|
||||||
FILTER_TYPE_BOOLEAN = 13
|
FILTER_TYPE_BOOLEAN = 13
|
||||||
FILTER_TYPE_PATTERN = 14
|
FILTER_TYPE_PATTERN = 14
|
||||||
FILTER_TYPE_SERIES = 15
|
FILTER_TYPE_SERIES = 15
|
||||||
@ -45,6 +46,9 @@ local redate = function ( ts )
|
|||||||
x.isdst = false
|
x.isdst = false
|
||||||
return os.time( x )
|
return os.time( x )
|
||||||
end
|
end
|
||||||
|
local unpack_address = function ( addr )
|
||||||
|
return { math.floor( addr / 16777216 ), math.floor( ( addr % 16777216 ) / 65536 ), math.floor( ( addr % 65536 ) / 256 ), addr % 256 }
|
||||||
|
end
|
||||||
|
|
||||||
----------------------------
|
----------------------------
|
||||||
-- StringPattern class
|
-- StringPattern class
|
||||||
@ -132,7 +136,7 @@ function AuthFilter( path, name )
|
|||||||
["trim"] = { type = FILTER_TYPE_STRING, args = { FILTER_TYPE_STRING, FILTER_TYPE_NUMBER }, def = function ( v, a, b ) return b > 0 and string.sub( a, 1, -b - 1 ) or string.sub( a, -b + 1 ) end },
|
["trim"] = { type = FILTER_TYPE_STRING, args = { FILTER_TYPE_STRING, FILTER_TYPE_NUMBER }, def = function ( v, a, b ) return b > 0 and string.sub( a, 1, -b - 1 ) or string.sub( a, -b + 1 ) end },
|
||||||
["crop"] = { type = FILTER_TYPE_STRING, args = { FILTER_TYPE_STRING, FILTER_TYPE_NUMBER }, def = function ( v, a, b ) return b > 0 and string.sub( a, 1, b ) or string.sub( a, b, -1 ) end },
|
["crop"] = { type = FILTER_TYPE_STRING, args = { FILTER_TYPE_STRING, FILTER_TYPE_NUMBER }, def = function ( v, a, b ) return b > 0 and string.sub( a, 1, b ) or string.sub( a, b, -1 ) end },
|
||||||
["size"] = { type = FILTER_TYPE_NUMBER, args = { FILTER_TYPE_SERIES }, def = function ( v, a ) return #a end },
|
["size"] = { type = FILTER_TYPE_NUMBER, args = { FILTER_TYPE_SERIES }, def = function ( v, a ) return #a end },
|
||||||
["elem"] = { type = FILTER_TYPE_STRING, args = { FILTER_TYPE_SERIES, FILTER_TYPE_NUMBER }, def = function ( v, a, b ) return a[ b ] or "" end },
|
["elem"] = { type = FILTER_TYPE_STRING, args = { FILTER_TYPE_SERIES, FILTER_TYPE_NUMBER }, def = function ( v, a, b ) return a[ b > 0 and b or #a + b + 1 ] or "" end },
|
||||||
["split"] = { type = FILTER_TYPE_SERIES, args = { FILTER_TYPE_STRING, FILTER_TYPE_STRING }, def = function ( v, a, b ) return string.split( a, b, true ) end },
|
["split"] = { type = FILTER_TYPE_SERIES, args = { FILTER_TYPE_STRING, FILTER_TYPE_STRING }, def = function ( v, a, b ) return string.split( a, b, true ) end },
|
||||||
["time"] = { type = FILTER_TYPE_TIMESPEC, args = { FILTER_TYPE_MOMENT }, def = function ( v, a ) return redate( a - v.epoch.value ) % 86400 end },
|
["time"] = { type = FILTER_TYPE_TIMESPEC, args = { FILTER_TYPE_MOMENT }, def = function ( v, a ) return redate( a - v.epoch.value ) % 86400 end },
|
||||||
["date"] = { type = FILTER_TYPE_DATESPEC, args = { FILTER_TYPE_MOMENT }, def = function ( v, a ) return math.floor( redate( a - v.epoch.value ) / 86400 ) end },
|
["date"] = { type = FILTER_TYPE_DATESPEC, args = { FILTER_TYPE_MOMENT }, def = function ( v, a ) return math.floor( redate( a - v.epoch.value ) / 86400 ) end },
|
||||||
@ -141,6 +145,9 @@ function AuthFilter( path, name )
|
|||||||
["after"] = { type = FILTER_TYPE_MOMENT, args = { FILTER_TYPE_MOMENT, FILTER_TYPE_PERIOD }, def = function ( v, a, b ) return a + b end },
|
["after"] = { type = FILTER_TYPE_MOMENT, args = { FILTER_TYPE_MOMENT, FILTER_TYPE_PERIOD }, def = function ( v, a, b ) return a + b end },
|
||||||
["day"] = { type = FILTER_TYPE_STRING, args = { FILTER_TYPE_MOMENT }, def = function ( v, a ) return os.date( "%a", a ) end },
|
["day"] = { type = FILTER_TYPE_STRING, args = { FILTER_TYPE_MOMENT }, def = function ( v, a ) return os.date( "%a", a ) end },
|
||||||
["at"] = { type = FILTER_TYPE_MOMENT, args = { FILTER_TYPE_STRING }, def = function ( v, a ) return localtime( a ) or 0 end },
|
["at"] = { type = FILTER_TYPE_MOMENT, args = { FILTER_TYPE_STRING }, def = function ( v, a ) return localtime( a ) or 0 end },
|
||||||
|
["ip"] = { type = FILTER_TYPE_STRING, args = { FILTER_TYPE_ADDRESS }, def = function ( v, a ) return table.concat( unpack_address( a ), "." ) end },
|
||||||
|
["count"] = { type = FILTER_TYPE_NUMBER, args = { FILTER_TYPE_SERIES, FILTER_TYPE_STRING }, def = function ( v, a, b ) local t = 0; for i, v in ipairs( a ) do if v == b then t = t + 1; end; end; return t end },
|
||||||
|
["clip"] = { type = FILTER_TYPE_SERIES, args = { FILTER_TYPE_SERIES, FILTER_TYPE_NUMBER }, def = function ( v, a, b ) local x = { }; local s = b < 0 and #a + b + 1 or 0; for i = 0, math.abs( b ) do table.insert( x, a[ s + i ] ); end; return x; end },
|
||||||
}
|
}
|
||||||
|
|
||||||
----------------------------
|
----------------------------
|
||||||
@ -210,7 +217,7 @@ function AuthFilter( path, name )
|
|||||||
end
|
end
|
||||||
elseif find_token( "^%$([a-zA-Z0-9_]+)$" ) then
|
elseif find_token( "^%$([a-zA-Z0-9_]+)$" ) then
|
||||||
local name = ref[ 1 ]
|
local name = ref[ 1 ]
|
||||||
if not vars[ name ] then
|
if not vars[ name ] or vars[ name ].value == nil then
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
t = vars[ name ].type
|
t = vars[ name ].type
|
||||||
@ -225,7 +232,7 @@ function AuthFilter( path, name )
|
|||||||
for line in file:lines( ) do
|
for line in file:lines( ) do
|
||||||
table.insert( v, line )
|
table.insert( v, line )
|
||||||
end
|
end
|
||||||
elseif find_token( "^/([a-zA-Z0-9+/]*),([tds]);$" ) then
|
elseif find_token( "^/([a-zA-Z0-9+/]*),([stda]);$" ) then
|
||||||
t = FILTER_TYPE_PATTERN
|
t = FILTER_TYPE_PATTERN
|
||||||
local phrase = minetest.decode_base64( ref[ 1 ] )
|
local phrase = minetest.decode_base64( ref[ 1 ] )
|
||||||
if ref[ 2 ] == "s" then
|
if ref[ 2 ] == "s" then
|
||||||
@ -262,6 +269,11 @@ function AuthFilter( path, name )
|
|||||||
local datespec = os.date( "*t", value )
|
local datespec = os.date( "*t", value )
|
||||||
return { datespec.day, datespec.month, datespec.year }
|
return { datespec.day, datespec.month, datespec.year }
|
||||||
end )
|
end )
|
||||||
|
elseif ref[ 2 ] == "a" then
|
||||||
|
phrase = string.split( phrase, ".", false )
|
||||||
|
v = NumberPattern( phrase, { [FILTER_TYPE_ADDRESS] = true }, { "%d?%d?%d", "%d?%d?%d", "%d?%d?%d", "%d?%d?%d" }, function ( value )
|
||||||
|
return unpack_address( value )
|
||||||
|
end )
|
||||||
end
|
end
|
||||||
if not v then
|
if not v then
|
||||||
return nil
|
return nil
|
||||||
@ -298,7 +310,10 @@ function AuthFilter( path, name )
|
|||||||
end )
|
end )
|
||||||
elseif find_token( "^-?%d+$" ) or find_token( "^-?%d*%.%d+$" ) then
|
elseif find_token( "^-?%d+$" ) or find_token( "^-?%d*%.%d+$" ) then
|
||||||
t = FILTER_TYPE_NUMBER
|
t = FILTER_TYPE_NUMBER
|
||||||
v = tonumber( token )
|
v = tonumber( ref[ 1 ] )
|
||||||
|
elseif find_token( "^(%d+)%.(%d+)%.(%d+)%.(%d+)$" ) then
|
||||||
|
t = FILTER_TYPE_ADDRESS
|
||||||
|
v = tonumber( ref[ 1 ] ) * 16777216 + tonumber( ref[ 2 ] ) * 65536 + tonumber( ref[ 3 ] ) * 256 + tonumber( ref[ 4 ] )
|
||||||
else
|
else
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
@ -329,7 +344,7 @@ function AuthFilter( path, name )
|
|||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
self.refresh = function ( )
|
self.refresh = function ( )
|
||||||
local file = io.open( path .. "/" .. name, "rb" )
|
local file = io.open( path .. "/" .. name, "r" )
|
||||||
if not file then
|
if not file then
|
||||||
error( "The specified ruleset file does not exist." )
|
error( "The specified ruleset file does not exist." )
|
||||||
end
|
end
|
||||||
@ -342,7 +357,7 @@ function AuthFilter( path, name )
|
|||||||
line = string.gsub( line, "'(.-)'", function ( str )
|
line = string.gsub( line, "'(.-)'", function ( str )
|
||||||
return "'" .. encode_base64( str ) .. ";"
|
return "'" .. encode_base64( str ) .. ";"
|
||||||
end )
|
end )
|
||||||
line = string.gsub( line, "/(.-)/([tds]?)", function ( a, b )
|
line = string.gsub( line, "/(.-)/([stda]?)", function ( a, b )
|
||||||
return "/" .. encode_base64( a ) .. "," .. ( b == "" and "s" or b ) .. ";"
|
return "/" .. encode_base64( a ) .. "," .. ( b == "" and "s" or b ) .. ";"
|
||||||
end )
|
end )
|
||||||
line = string.gsub( line, "%b()", function ( str )
|
line = string.gsub( line, "%b()", function ( str )
|
||||||
@ -374,12 +389,9 @@ function AuthFilter( path, name )
|
|||||||
-- skip no-op statements
|
-- skip no-op statements
|
||||||
|
|
||||||
elseif stmt[ 1 ] == "continue" then
|
elseif stmt[ 1 ] == "continue" then
|
||||||
|
if not rule then return trace( "Unexpected 'continue' statement in ruleset", num ) end
|
||||||
if #stmt ~= 1 then return trace( "Invalid 'continue' statement in ruleset", num ) end
|
if #stmt ~= 1 then return trace( "Invalid 'continue' statement in ruleset", num ) end
|
||||||
|
|
||||||
if rule == nil then
|
|
||||||
return trace( "No ruleset declared", num )
|
|
||||||
end
|
|
||||||
|
|
||||||
if evaluate( rule ) then
|
if evaluate( rule ) then
|
||||||
return ( rule.mode == FILTER_MODE_FAIL and note or nil )
|
return ( rule.mode == FILTER_MODE_FAIL and note or nil )
|
||||||
end
|
end
|
||||||
@ -398,7 +410,7 @@ function AuthFilter( path, name )
|
|||||||
note = oper.value
|
note = oper.value
|
||||||
|
|
||||||
elseif stmt[ 1 ] == "pass" or stmt[ 1 ] == "fail" then
|
elseif stmt[ 1 ] == "pass" or stmt[ 1 ] == "fail" then
|
||||||
if rule then return trace( "Missing continue statement in ruleset", num ) end
|
if rule then return trace( "Missing 'continue' statement in ruleset", num ) end
|
||||||
if #stmt ~= 2 then return trace( "Invalid 'pass' or 'fail' statement in ruleset", num ) end
|
if #stmt ~= 2 then return trace( "Invalid 'pass' or 'fail' statement in ruleset", num ) end
|
||||||
|
|
||||||
rule = { }
|
rule = { }
|
||||||
@ -419,6 +431,7 @@ function AuthFilter( path, name )
|
|||||||
rule.expr = { }
|
rule.expr = { }
|
||||||
|
|
||||||
elseif stmt[ 1 ] == "when" or stmt[ 1 ] == "until" then
|
elseif stmt[ 1 ] == "when" or stmt[ 1 ] == "until" then
|
||||||
|
if not rule then return trace( "Unexpected 'when' or 'until' statement in ruleset", num ) end
|
||||||
if #stmt ~= 4 then return trace( "Invalid 'when' or 'until' statement in ruleset", num ) end
|
if #stmt ~= 4 then return trace( "Invalid 'when' or 'until' statement in ruleset", num ) end
|
||||||
|
|
||||||
local cond = ( { ["when"] = FILTER_COND_TRUE, ["until"] = FILTER_COND_FALSE } )[ stmt[ 1 ] ]
|
local cond = ( { ["when"] = FILTER_COND_TRUE, ["until"] = FILTER_COND_FALSE } )[ stmt[ 1 ] ]
|
||||||
@ -462,6 +475,7 @@ function AuthFilter( path, name )
|
|||||||
table.insert( rule.expr, expr )
|
table.insert( rule.expr, expr )
|
||||||
|
|
||||||
elseif stmt[ 1 ] == "if" or stmt[ 1 ] == "unless" then
|
elseif stmt[ 1 ] == "if" or stmt[ 1 ] == "unless" then
|
||||||
|
if not rule then return trace( "Unexpected 'if' or 'unless' statement in ruleset", num ) end
|
||||||
if #stmt ~= 4 then return trace( "Invalid 'if' or 'unless' statement in ruleset", num ) end
|
if #stmt ~= 4 then return trace( "Invalid 'if' or 'unless' statement in ruleset", num ) end
|
||||||
|
|
||||||
local cond = ( { ["if"] = FILTER_COND_TRUE, ["unless"] = FILTER_COND_FALSE } )[ stmt[ 1 ] ]
|
local cond = ( { ["if"] = FILTER_COND_TRUE, ["unless"] = FILTER_COND_FALSE } )[ stmt[ 1 ] ]
|
||||||
|
27
init.lua
27
init.lua
@ -1,5 +1,5 @@
|
|||||||
--------------------------------------------------------
|
--------------------------------------------------------
|
||||||
-- Minetest :: Auth Redux Mod v2.7 (auth_rx)
|
-- Minetest :: Auth Redux Mod v2.9 (auth_rx)
|
||||||
--
|
--
|
||||||
-- See README.txt for licensing and release notes.
|
-- See README.txt for licensing and release notes.
|
||||||
-- Copyright (c) 2017-2018, Leslie E. Krause
|
-- Copyright (c) 2017-2018, Leslie E. Krause
|
||||||
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
dofile( minetest.get_modpath( "auth_rx" ) .. "/filter.lua" )
|
dofile( minetest.get_modpath( "auth_rx" ) .. "/filter.lua" )
|
||||||
dofile( minetest.get_modpath( "auth_rx" ) .. "/db.lua" )
|
dofile( minetest.get_modpath( "auth_rx" ) .. "/db.lua" )
|
||||||
|
dofile( minetest.get_modpath( "auth_rx" ) .. "/watchdog.lua" )
|
||||||
|
|
||||||
-----------------------------------------------------
|
-----------------------------------------------------
|
||||||
-- Registered Authentication Handler
|
-- Registered Authentication Handler
|
||||||
@ -14,6 +15,7 @@ dofile( minetest.get_modpath( "auth_rx" ) .. "/db.lua" )
|
|||||||
|
|
||||||
local auth_filter = AuthFilter( minetest.get_worldpath( ), "greenlist.mt" )
|
local auth_filter = AuthFilter( minetest.get_worldpath( ), "greenlist.mt" )
|
||||||
local auth_db = AuthDatabase( minetest.get_worldpath( ), "auth.db" )
|
local auth_db = AuthDatabase( minetest.get_worldpath( ), "auth.db" )
|
||||||
|
local auth_watchdog = AuthWatchdog( )
|
||||||
|
|
||||||
local get_minetest_config = core.setting_get -- backwards compatibility
|
local get_minetest_config = core.setting_get -- backwards compatibility
|
||||||
|
|
||||||
@ -41,14 +43,21 @@ function pack_privileges( privileges )
|
|||||||
return assigned_privs
|
return assigned_privs
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function convert_ipv4( str )
|
||||||
|
local ref = string.split( str, ".", false )
|
||||||
|
return tonumber( ref[ 1 ] ) * 16777216 + tonumber( ref[ 2 ] ) * 65536 + tonumber( ref[ 3 ] ) * 256 + tonumber( ref[ 4 ] )
|
||||||
|
end
|
||||||
|
|
||||||
if minetest.register_on_auth_fail then
|
if minetest.register_on_auth_fail then
|
||||||
minetest.register_on_auth_fail( function ( player_name, player_ip )
|
minetest.register_on_auth_fail( function ( player_name, player_ip )
|
||||||
auth_db.on_login_failure( player_name, player_ip )
|
auth_db.on_login_failure( player_name, player_ip )
|
||||||
|
auth_watchdog.on_failure( convert_ipv4( player_ip ) )
|
||||||
end )
|
end )
|
||||||
end
|
end
|
||||||
|
|
||||||
minetest.register_on_prejoinplayer( function ( player_name, player_ip )
|
minetest.register_on_prejoinplayer( function ( player_name, player_ip )
|
||||||
local rec = auth_db.select_record( player_name )
|
local rec = auth_db.select_record( player_name )
|
||||||
|
local res = auth_watchdog.get_metadata( convert_ipv4( player_ip ) )
|
||||||
|
|
||||||
if rec then
|
if rec then
|
||||||
auth_db.on_login_attempt( player_name, player_ip )
|
auth_db.on_login_attempt( player_name, player_ip )
|
||||||
@ -56,7 +65,7 @@ minetest.register_on_prejoinplayer( function ( player_name, player_ip )
|
|||||||
-- prevent creation of case-insensitive duplicate accounts
|
-- prevent creation of case-insensitive duplicate accounts
|
||||||
local uname = string.lower( player_name )
|
local uname = string.lower( player_name )
|
||||||
for cname in auth_db.records( ) do
|
for cname in auth_db.records( ) do
|
||||||
if string.lower( cname ) == uname then
|
if string.lower( cname ) == uname then
|
||||||
return string.format( "A player named %s already exists on this server.", cname )
|
return string.format( "A player named %s already exists on this server.", cname )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -64,7 +73,7 @@ minetest.register_on_prejoinplayer( function ( player_name, player_ip )
|
|||||||
|
|
||||||
local filter_err = auth_filter.process( {
|
local filter_err = auth_filter.process( {
|
||||||
name = { type = FILTER_TYPE_STRING, value = player_name },
|
name = { type = FILTER_TYPE_STRING, value = player_name },
|
||||||
addr = { type = FILTER_TYPE_STRING, value = player_ip },
|
addr = { type = FILTER_TYPE_ADDRESS, value = convert_ipv4( player_ip ) },
|
||||||
is_new = { type = FILTER_TYPE_BOOLEAN, value = rec == nil },
|
is_new = { type = FILTER_TYPE_BOOLEAN, value = rec == nil },
|
||||||
privs_list = { type = FILTER_TYPE_SERIES, value = rec and rec.assigned_privs or { } },
|
privs_list = { type = FILTER_TYPE_SERIES, value = rec and rec.assigned_privs or { } },
|
||||||
users_list = { type = FILTER_TYPE_SERIES, value = auth_db.search( true ) },
|
users_list = { type = FILTER_TYPE_SERIES, value = auth_db.search( true ) },
|
||||||
@ -77,8 +86,16 @@ minetest.register_on_prejoinplayer( function ( player_name, player_ip )
|
|||||||
uptime = { type = FILTER_TYPE_PERIOD, value = minetest.get_server_uptime( ) },
|
uptime = { type = FILTER_TYPE_PERIOD, value = minetest.get_server_uptime( ) },
|
||||||
oldlogin = { type = FILTER_TYPE_MOMENT, value = rec and rec.oldlogin or 0 },
|
oldlogin = { type = FILTER_TYPE_MOMENT, value = rec and rec.oldlogin or 0 },
|
||||||
newlogin = { type = FILTER_TYPE_MOMENT, value = rec and rec.newlogin or 0 },
|
newlogin = { type = FILTER_TYPE_MOMENT, value = rec and rec.newlogin or 0 },
|
||||||
|
ip_names_list = { type = FILTER_TYPE_SERIES, value = res.previous_names or { } },
|
||||||
|
ip_prelogin = { type = FILTER_TYPE_MOMENT, value = res.prelogin or 0 },
|
||||||
|
ip_oldcheck = { type = FILTER_TYPE_MOMENT, value = res.oldcheck or 0 },
|
||||||
|
ip_newcheck = { type = FILTER_TYPE_MOMENT, value = res.newcheck or 0 },
|
||||||
|
ip_failures = { type = FILTER_TYPE_NUMBER, value = res.count_failures or 0 },
|
||||||
|
ip_attempts = { type = FILTER_TYPE_NUMBER, value = res.count_attempts or 0 }
|
||||||
} )
|
} )
|
||||||
|
|
||||||
|
auth_watchdog.on_attempt( convert_ipv4( player_ip ), player_name )
|
||||||
|
|
||||||
return filter_err
|
return filter_err
|
||||||
end )
|
end )
|
||||||
|
|
||||||
@ -86,6 +103,10 @@ minetest.register_on_joinplayer( function ( player )
|
|||||||
local player_name = player:get_player_name( )
|
local player_name = player:get_player_name( )
|
||||||
auth_db.on_login_success( player_name, "0.0.0.0" )
|
auth_db.on_login_success( player_name, "0.0.0.0" )
|
||||||
auth_db.on_session_opened( player_name )
|
auth_db.on_session_opened( player_name )
|
||||||
|
minetest.after( 0.0, function ( )
|
||||||
|
-- hack since player status not immediately available on some MT versions
|
||||||
|
auth_watchdog.on_success( convert_ipv4( minetest.get_player_information( player_name ).address ) )
|
||||||
|
end )
|
||||||
end )
|
end )
|
||||||
|
|
||||||
minetest.register_on_leaveplayer( function ( player )
|
minetest.register_on_leaveplayer( function ( player )
|
||||||
|
47
watchdog.lua
Normal file
47
watchdog.lua
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
--------------------------------------------------------
|
||||||
|
-- Minetest :: Auth Redux Mod v2.9 (auth_rx)
|
||||||
|
--
|
||||||
|
-- See README.txt for licensing and release notes.
|
||||||
|
-- Copyright (c) 2017-2018, Leslie E. Krause
|
||||||
|
--------------------------------------------------------
|
||||||
|
|
||||||
|
----------------------------
|
||||||
|
-- AuthWatchdog Class
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
function AuthWatchdog( )
|
||||||
|
local self = { }
|
||||||
|
local clients = { }
|
||||||
|
|
||||||
|
self.get_metadata = function ( ip )
|
||||||
|
return clients[ ip ] or { }
|
||||||
|
end
|
||||||
|
self.on_failure = function ( ip )
|
||||||
|
local meta = clients[ ip ]
|
||||||
|
|
||||||
|
meta.count_failures = meta.count_failures + 1
|
||||||
|
meta.newcheck = os.time( )
|
||||||
|
if not meta.oldcheck then
|
||||||
|
meta.oldcheck = os.time( )
|
||||||
|
end
|
||||||
|
|
||||||
|
return meta
|
||||||
|
end
|
||||||
|
self.on_success = function ( ip )
|
||||||
|
clients[ ip ] = nil
|
||||||
|
end
|
||||||
|
self.on_attempt = function ( ip, name )
|
||||||
|
if not clients[ ip ] then
|
||||||
|
clients[ ip ] = { count_attempts = 0, count_failures = 0, previous_names = { } }
|
||||||
|
end
|
||||||
|
local meta = clients[ ip ]
|
||||||
|
|
||||||
|
meta.count_attempts = meta.count_attempts + 1
|
||||||
|
meta.prelogin = os.time( )
|
||||||
|
table.insert( meta.previous_names, name )
|
||||||
|
|
||||||
|
return meta
|
||||||
|
end
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
Loading…
x
Reference in New Issue
Block a user