Build 10
- implemented time and date datatypes for rulesets - updated code samples with latest feature-set - added time-related functions for use by rulesets - added time-related variables for use by rulesets - minor formatting fixes to source code - optimized comparison algorithm in ruleset parser
This commit is contained in:
parent
a0799fe6a4
commit
61d1fe67e7
10
README.txt
10
README.txt
@ -1,4 +1,4 @@
|
|||||||
Auth Redux Mod v2.6b
|
Auth Redux Mod v2.7b
|
||||||
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.
|
||||||
@ -71,6 +71,14 @@ Version 2.6b (19-Jul-2018)
|
|||||||
- tweaked lexer to skip comments on ruleset loading
|
- tweaked lexer to skip comments on ruleset loading
|
||||||
- added search function to AuthDatabase class
|
- added search function to AuthDatabase class
|
||||||
|
|
||||||
|
Version 2.7b (21-Jul-2018)
|
||||||
|
- implemented time and date datatypes for rulesets
|
||||||
|
- updated code samples with latest feature-set
|
||||||
|
- added time-related functions for use by rulesets
|
||||||
|
- added time-related variables for use by rulesets
|
||||||
|
- minor formatting fixes to source code
|
||||||
|
- optimized comparison algorithm in ruleset parser
|
||||||
|
|
||||||
Installation
|
Installation
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
|
58
filter.lua
58
filter.lua
@ -1,15 +1,19 @@
|
|||||||
--------------------------------------------------------
|
--------------------------------------------------------
|
||||||
-- Minetest :: Auth Redux Mod v2.6 (auth_rx)
|
-- Minetest :: Auth Redux Mod v2.7 (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 = 11
|
||||||
FILTER_TYPE_BOOLEAN = 12
|
FILTER_TYPE_NUMBER = 12
|
||||||
FILTER_TYPE_NUMBER = 13
|
FILTER_TYPE_BOOLEAN = 13
|
||||||
FILTER_TYPE_PATTERN = 14
|
FILTER_TYPE_PATTERN = 14
|
||||||
FILTER_TYPE_SERIES = 15
|
FILTER_TYPE_SERIES = 15
|
||||||
|
FILTER_TYPE_PERIOD = 16
|
||||||
|
FILTER_TYPE_MOMENT = 17
|
||||||
|
FILTER_TYPE_DATESPEC = 18
|
||||||
|
FILTER_TYPE_TIMESPEC = 19
|
||||||
FILTER_MODE_FAIL = 20
|
FILTER_MODE_FAIL = 20
|
||||||
FILTER_MODE_PASS = 21
|
FILTER_MODE_PASS = 21
|
||||||
FILTER_BOOL_AND = 30
|
FILTER_BOOL_AND = 30
|
||||||
@ -60,6 +64,11 @@ function AuthFilter( path, name )
|
|||||||
["size"] = { type = FILTER_TYPE_NUMBER, args = { FILTER_TYPE_SERIES }, def = function ( a ) return #a end },
|
["size"] = { type = FILTER_TYPE_NUMBER, args = { FILTER_TYPE_SERIES }, def = function ( a ) return #a end },
|
||||||
["elem"] = { type = FILTER_TYPE_STRING, args = { FILTER_TYPE_SERIES, FILTER_TYPE_NUMBER }, def = function ( a, b ) return a[ b ] or "" end },
|
["elem"] = { type = FILTER_TYPE_STRING, args = { FILTER_TYPE_SERIES, FILTER_TYPE_NUMBER }, def = function ( a, b ) return a[ b ] or "" end },
|
||||||
["split"] = { type = FILTER_TYPE_SERIES, args = { FILTER_TYPE_STRING, FILTER_TYPE_STRING }, def = function ( a, b ) return string.split( a, b, true ) end },
|
["split"] = { type = FILTER_TYPE_SERIES, args = { FILTER_TYPE_STRING, FILTER_TYPE_STRING }, def = function ( a, b ) return string.split( a, b, true ) end },
|
||||||
|
["time"] = { type = FILTER_TYPE_TIMESPEC, args = { FILTER_TYPE_MOMENT }, def = function ( a ) return a % 86400 end },
|
||||||
|
["date"] = { type = FILTER_TYPE_DATESPEC, args = { FILTER_TYPE_MOMENT }, def = function ( a ) return math.floor( a / 86400 ) end },
|
||||||
|
["age"] = { type = FILTER_TYPE_PERIOD, args = { FILTER_TYPE_MOMENT }, def = function ( a ) return os.time( ) - a end }, -- FIXME: use global clock variable
|
||||||
|
["before"] = { type = FILTER_TYPE_MOMENT, args = { FILTER_TYPE_MOMENT, FILTER_TYPE_PERIOD }, def = function ( a, b ) return a - b end },
|
||||||
|
["after"] = { type = FILTER_TYPE_MOMENT, args = { FILTER_TYPE_MOMENT, FILTER_TYPE_PERIOD }, def = function ( a, b ) return a + b end },
|
||||||
}
|
}
|
||||||
|
|
||||||
----------------------------
|
----------------------------
|
||||||
@ -169,6 +178,27 @@ function AuthFilter( path, name )
|
|||||||
t = FILTER_TYPE_PATTERN
|
t = FILTER_TYPE_PATTERN
|
||||||
v = decode_base64( ref[ 1 ] )
|
v = decode_base64( ref[ 1 ] )
|
||||||
v = "^" .. string.gsub( v, ".", sanitizer ) .. "$"
|
v = "^" .. string.gsub( v, ".", sanitizer ) .. "$"
|
||||||
|
elseif find_token( "^(%d+)([ydhms])$" ) then
|
||||||
|
local factor = { y = 31536000, w = 604800, d = 86400, h = 3600, m = 60, s = 1 }
|
||||||
|
t = FILTER_TYPE_PERIOD
|
||||||
|
v = tonumber( ref[ 1 ] ) * factor[ ref[ 2 ] ]
|
||||||
|
elseif find_token( "^([-+]%d+)([ydhms])$" ) then
|
||||||
|
local factor = { y = 31536000, w = 604800, d = 86400, h = 3600, m = 60, s = 1 }
|
||||||
|
local origin = string.byte( ref[ 1 ] ) == 45 and vars.clock.value or 0
|
||||||
|
t = FILTER_TYPE_MOMENT
|
||||||
|
v = origin + tonumber( ref[ 1 ] ) * factor[ ref[ 2 ] ]
|
||||||
|
elseif find_token( "^(%d?%d):(%d%d):(%d%d)$" ) or find_token( "^(%d?%d):(%d%d)$" ) then
|
||||||
|
local timespec = {
|
||||||
|
isdst = true, day = 1, month = 1, year = 1970, hour = tonumber( ref[ 1 ] ), min = tonumber( ref[ 2 ] ), sec = ref[ 3 ] and tonumber( ref[ 3 ] ) or 0,
|
||||||
|
}
|
||||||
|
t = FILTER_TYPE_TIMESPEC
|
||||||
|
v = os.time( timespec )
|
||||||
|
elseif find_token( "^(%d%d)%-(%d%d)%-(%d%d%d%d)$" ) then
|
||||||
|
local datespec = {
|
||||||
|
isdst = true, day = tonumber( ref[ 1 ] ), month = tonumber( ref[ 2 ] ), year = tonumber( ref[ 3 ] ), hour = 0,
|
||||||
|
}
|
||||||
|
t = FILTER_TYPE_DATESPEC
|
||||||
|
v = math.floor( os.time( datespec ) / 86400 )
|
||||||
elseif find_token( "^'([a-zA-Z0-9+/]*);$" ) then
|
elseif find_token( "^'([a-zA-Z0-9+/]*);$" ) then
|
||||||
t = FILTER_TYPE_STRING
|
t = FILTER_TYPE_STRING
|
||||||
v = decode_base64( ref[ 1 ] )
|
v = decode_base64( ref[ 1 ] )
|
||||||
@ -244,7 +274,8 @@ function AuthFilter( path, name )
|
|||||||
|
|
||||||
vars[ "true" ] = { type = FILTER_TYPE_BOOLEAN, value = true }
|
vars[ "true" ] = { type = FILTER_TYPE_BOOLEAN, value = true }
|
||||||
vars[ "false" ] = { type = FILTER_TYPE_BOOLEAN, value = false }
|
vars[ "false" ] = { type = FILTER_TYPE_BOOLEAN, value = false }
|
||||||
vars[ "time" ] = { type = FILTER_TYPE_NUMBER, value = os.time( ) }
|
vars[ "clock" ] = { type = FILTER_TYPE_MOMENT, value = os.time( ) }
|
||||||
|
vars[ "epoch" ] = { type = FILTER_TYPE_MOMENT, value = 0 }
|
||||||
|
|
||||||
for num, line in ipairs( src ) do
|
for num, line in ipairs( src ) do
|
||||||
local stmt = string.split( line, " ", false )
|
local stmt = string.split( line, " ", false )
|
||||||
@ -356,21 +387,24 @@ function AuthFilter( path, name )
|
|||||||
return trace( "Unrecognized operands in ruleset", num )
|
return trace( "Unrecognized operands in ruleset", num )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- only allow comparisons of appropriate and equivalent datatypes
|
||||||
|
local do_math = { [FILTER_TYPE_STRING] = false, [FILTER_TYPE_NUMBER] = true, [FILTER_TYPE_PERIOD] = true, [FILTER_TYPE_MOMENT] = true, [FILTER_TYPE_DATESPEC] = true, [FILTER_TYPE_TIMESPEC] = true }
|
||||||
|
|
||||||
local expr
|
local expr
|
||||||
if comp == FILTER_COMP_EQ and oper1.type == oper2.type and oper1.type ~= FILTER_TYPE_SERIES and oper1.type ~= FILTER_TYPE_PATTERN then
|
if comp == FILTER_COMP_EQ and oper1.type == oper2.type and oper1.type ~= FILTER_TYPE_SERIES and oper1.type ~= FILTER_TYPE_PATTERN then
|
||||||
expr = ( oper1.value == oper2.value )
|
expr = ( oper1.value == oper2.value )
|
||||||
|
elseif comp == FILTER_COMP_GT and oper1.type == oper2.type and do_math[ oper2.type ] then
|
||||||
|
expr = ( oper1.value > oper2.value )
|
||||||
|
elseif comp == FILTER_COMP_GTE and oper1.type == oper2.type and do_math[ oper2.type ] then
|
||||||
|
expr = ( oper1.value >= oper2.value )
|
||||||
|
elseif comp == FILTER_COMP_LT and oper1.type == oper2.type and do_math[ oper2.type ] then
|
||||||
|
expr = ( oper1.value < oper2.value )
|
||||||
|
elseif comp == FILTER_COMP_LTE and oper1.type == oper2.type and do_math[ oper2.type ] then
|
||||||
|
expr = ( oper1.value <= oper2.value )
|
||||||
elseif comp == FILTER_COMP_IS and oper1.type == FILTER_TYPE_STRING and oper2.type == FILTER_TYPE_STRING then
|
elseif comp == FILTER_COMP_IS and oper1.type == FILTER_TYPE_STRING and oper2.type == FILTER_TYPE_STRING then
|
||||||
expr = ( string.upper( oper1.value ) == string.upper( oper2.value ) )
|
expr = ( string.upper( oper1.value ) == string.upper( oper2.value ) )
|
||||||
elseif comp == FILTER_COMP_IS and oper1.type == FILTER_TYPE_STRING and oper2.type == FILTER_TYPE_PATTERN then
|
elseif comp == FILTER_COMP_IS and oper1.type == FILTER_TYPE_STRING and oper2.type == FILTER_TYPE_PATTERN then
|
||||||
expr = ( string.find( oper1.value, oper2.value ) == 1 )
|
expr = ( string.find( oper1.value, oper2.value ) == 1 )
|
||||||
elseif comp == FILTER_COMP_GT and oper1.type == FILTER_TYPE_NUMBER and oper2.type == FILTER_TYPE_NUMBER then
|
|
||||||
expr = ( oper1.value > oper2.value )
|
|
||||||
elseif comp == FILTER_COMP_LT and oper1.type == FILTER_TYPE_NUMBER and oper2.type == FILTER_TYPE_NUMBER then
|
|
||||||
expr = ( oper1.value < oper2.value )
|
|
||||||
elseif comp == FILTER_COMP_GTE and oper1.type == FILTER_TYPE_NUMBER and oper2.type == FILTER_TYPE_NUMBER then
|
|
||||||
expr = ( oper1.value >= oper2.value )
|
|
||||||
elseif comp == FILTER_COMP_LTE and oper1.type == FILTER_TYPE_NUMBER and oper2.type == FILTER_TYPE_NUMBER then
|
|
||||||
expr = ( oper1.value <= oper2.value )
|
|
||||||
else
|
else
|
||||||
return trace( "Mismatched operands in ruleset", num )
|
return trace( "Mismatched operands in ruleset", num )
|
||||||
end
|
end
|
||||||
|
5
init.lua
5
init.lua
@ -1,5 +1,5 @@
|
|||||||
--------------------------------------------------------
|
--------------------------------------------------------
|
||||||
-- Minetest :: Auth Redux Mod v2.6 (auth_rx)
|
-- Minetest :: Auth Redux Mod v2.7 (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
|
||||||
@ -74,6 +74,9 @@ minetest.register_on_prejoinplayer( function ( player_name, player_ip )
|
|||||||
failures = { type = FILTER_TYPE_NUMBER, value = rec and rec.total_failures or 0 },
|
failures = { type = FILTER_TYPE_NUMBER, value = rec and rec.total_failures or 0 },
|
||||||
attempts = { type = FILTER_TYPE_NUMBER, value = rec and rec.total_attempts or 0 },
|
attempts = { type = FILTER_TYPE_NUMBER, value = rec and rec.total_attempts or 0 },
|
||||||
owner = { type = FILTER_TYPE_STRING, value = get_minetest_config( "name" ) },
|
owner = { type = FILTER_TYPE_STRING, value = get_minetest_config( "name" ) },
|
||||||
|
uptime = { type = FILTER_TYPE_PERIOD, value = minetest.get_server_uptime( ) },
|
||||||
|
oldlogin = { type = FILTER_TYPE_MOMENT, value = rec and rec.oldlogin or 0 },
|
||||||
|
newlogin = { type = FILTER_TYPE_MOMENT, value = rec and rec.newlogin or 0 },
|
||||||
} )
|
} )
|
||||||
|
|
||||||
return filter_err
|
return filter_err
|
||||||
|
144
samples.mt
144
samples.mt
@ -1,16 +1,3 @@
|
|||||||
#####################################################################
|
|
||||||
#
|
|
||||||
# disallow new players whenever server is overloaded
|
|
||||||
#
|
|
||||||
#####################################################################
|
|
||||||
|
|
||||||
try "There are too many players online right now."
|
|
||||||
|
|
||||||
fail all
|
|
||||||
if $is_new eq $true
|
|
||||||
if $cur_users gt 20
|
|
||||||
continue
|
|
||||||
|
|
||||||
#####################################################################
|
#####################################################################
|
||||||
#
|
#
|
||||||
# only allow administrator access (by username or IP address)
|
# only allow administrator access (by username or IP address)
|
||||||
@ -23,6 +10,8 @@ if $addr eq "172.16.100.2"
|
|||||||
if $name eq "admin"
|
if $name eq "admin"
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
fail now
|
||||||
|
|
||||||
#####################################################################
|
#####################################################################
|
||||||
#
|
#
|
||||||
# block a range of IP addresses using wildcards
|
# block a range of IP addresses using wildcards
|
||||||
@ -41,7 +30,7 @@ pass now
|
|||||||
|
|
||||||
#####################################################################
|
#####################################################################
|
||||||
#
|
#
|
||||||
# only allow access from whitelisted users
|
# only allow access from whitelisted players
|
||||||
#
|
#
|
||||||
#####################################################################
|
#####################################################################
|
||||||
|
|
||||||
@ -56,7 +45,7 @@ fall now
|
|||||||
|
|
||||||
#####################################################################
|
#####################################################################
|
||||||
#
|
#
|
||||||
# never allow access from blacklisted users
|
# never allow access from blacklisted players
|
||||||
#
|
#
|
||||||
#####################################################################
|
#####################################################################
|
||||||
|
|
||||||
@ -69,10 +58,133 @@ pass now
|
|||||||
|
|
||||||
#####################################################################
|
#####################################################################
|
||||||
#
|
#
|
||||||
# notify users that the server is unavailable right now
|
# notify players that the server is unavailable right now
|
||||||
#
|
#
|
||||||
#####################################################################
|
#####################################################################
|
||||||
|
|
||||||
try "The server is temporarily offline for maintenance."
|
try "The server is temporarily offline for maintenance."
|
||||||
|
|
||||||
fail now
|
fail now
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
#
|
||||||
|
# disallow players with all uppercase names
|
||||||
|
#
|
||||||
|
#####################################################################
|
||||||
|
|
||||||
|
try "Sorry, we do not accept all uppercase player names."
|
||||||
|
|
||||||
|
fail all
|
||||||
|
$name eq uc($name)
|
||||||
|
continue
|
||||||
|
|
||||||
|
pass now
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
#
|
||||||
|
# disallow players with very short or very long names
|
||||||
|
#
|
||||||
|
#####################################################################
|
||||||
|
|
||||||
|
try "Sorry, this player name is too long or too short."
|
||||||
|
|
||||||
|
fail any
|
||||||
|
$name->len() gt 20
|
||||||
|
$name->len() lt 3
|
||||||
|
continue
|
||||||
|
|
||||||
|
pass now
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
#
|
||||||
|
# disallow users that appear to be bots or guests
|
||||||
|
#
|
||||||
|
#####################################################################
|
||||||
|
|
||||||
|
try "Sorry, we do not accept autogenerated player names."
|
||||||
|
|
||||||
|
fail any
|
||||||
|
if $name is /;*;*##/
|
||||||
|
if $name is /;*;*###/
|
||||||
|
if $name is /Player#/
|
||||||
|
if $name is /Player##/
|
||||||
|
if $name is /Guest#/
|
||||||
|
if $name is /Guest##/
|
||||||
|
continue
|
||||||
|
|
||||||
|
pass now
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
#
|
||||||
|
# disallow new players when the server is near capacity
|
||||||
|
#
|
||||||
|
#####################################################################
|
||||||
|
|
||||||
|
try "There are too many players online right now."
|
||||||
|
|
||||||
|
fail all
|
||||||
|
$is_new eq $true
|
||||||
|
$cur_users gte $max_users->mul(0.8)
|
||||||
|
continue
|
||||||
|
|
||||||
|
pass now
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
#
|
||||||
|
# prevent players from joining with a reserved name
|
||||||
|
#
|
||||||
|
#####################################################################
|
||||||
|
|
||||||
|
try "Sorry, this acccount has been permanently restricted."
|
||||||
|
|
||||||
|
fail all
|
||||||
|
$is_new eq $true
|
||||||
|
when ("moderator","server","client","owner","player","system","operator","minetest") is $name
|
||||||
|
continue
|
||||||
|
|
||||||
|
pass now
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
#
|
||||||
|
# disallow players that have been inactive for 90 days
|
||||||
|
#
|
||||||
|
#####################################################################
|
||||||
|
|
||||||
|
try "Sorry, this acccount has been disabled for inactivity."
|
||||||
|
|
||||||
|
fail all
|
||||||
|
if $is_new eq $false
|
||||||
|
if age($newlogin) gt 90d
|
||||||
|
continue
|
||||||
|
|
||||||
|
pass now
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
#
|
||||||
|
# disallow new players during the weekends
|
||||||
|
#
|
||||||
|
#####################################################################
|
||||||
|
|
||||||
|
try "Sorry, we are not accepting new players at this time."
|
||||||
|
|
||||||
|
fail now
|
||||||
|
if $is_new eq $true
|
||||||
|
when ("Sat","Sun") eq $clock->day()
|
||||||
|
continue
|
||||||
|
|
||||||
|
pass now
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
#
|
||||||
|
# prevent players from spam-logging the server
|
||||||
|
#
|
||||||
|
#####################################################################
|
||||||
|
|
||||||
|
try "You are doing that too much. Please wait awhile."
|
||||||
|
|
||||||
|
fail all
|
||||||
|
if $is_new eq $false
|
||||||
|
if age($newlogin) lt 15s
|
||||||
|
continue
|
||||||
|
|
||||||
|
pass now
|
||||||
|
Loading…
x
Reference in New Issue
Block a user