Auth Redux is a drop-in replacement for the builtin authentication handler of Minetest.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

init.lua 5.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. --------------------------------------------------------
  2. -- Minetest :: Auth Redux Mod v2.10 (auth_rx)
  3. --
  4. -- See README.txt for licensing and release notes.
  5. -- Copyright (c) 2017-2018, Leslie E. Krause
  6. --------------------------------------------------------
  7. dofile( minetest.get_modpath( "auth_rx" ) .. "/helpers.lua" )
  8. dofile( minetest.get_modpath( "auth_rx" ) .. "/filter.lua" )
  9. dofile( minetest.get_modpath( "auth_rx" ) .. "/db.lua" )
  10. dofile( minetest.get_modpath( "auth_rx" ) .. "/watchdog.lua" )
  11. local __commands = dofile( minetest.get_modpath( "auth_rx" ) .. "/commands.lua" )
  12. -----------------------------------------------------
  13. -- Registered Authentication Handler
  14. -----------------------------------------------------
  15. local auth_filter = AuthFilter( minetest.get_worldpath( ), "greenlist.mt" )
  16. local auth_db = AuthDatabase( minetest.get_worldpath( ), "auth.db" )
  17. local auth_watchdog = AuthWatchdog( )
  18. if minetest.register_on_auth_fail then
  19. minetest.register_on_auth_fail( function ( player_name, player_ip )
  20. auth_db.on_login_failure( player_name, player_ip )
  21. auth_watchdog.on_failure( convert_ipv4( player_ip ) )
  22. end )
  23. end
  24. minetest.register_on_prejoinplayer( function ( player_name, player_ip )
  25. local rec = auth_db.select_record( player_name )
  26. local meta = auth_watchdog.get_metadata( convert_ipv4( player_ip ) )
  27. if rec then
  28. auth_db.on_login_attempt( player_name, player_ip )
  29. else
  30. -- prevent creation of case-insensitive duplicate accounts
  31. local uname = string.lower( player_name )
  32. for cname in auth_db.records( ) do
  33. if string.lower( cname ) == uname then
  34. return string.format( "A player named %s already exists on this server.", cname )
  35. end
  36. end
  37. end
  38. local num, res = auth_filter.process( {
  39. name = { type = FILTER_TYPE_STRING, value = player_name },
  40. addr = { type = FILTER_TYPE_ADDRESS, value = convert_ipv4( player_ip ) },
  41. is_new = { type = FILTER_TYPE_BOOLEAN, value = rec == nil },
  42. privs_list = { type = FILTER_TYPE_SERIES, value = rec and rec.assigned_privs or { } },
  43. users_list = { type = FILTER_TYPE_SERIES, value = auth_db.search( true ) },
  44. cur_users = { type = FILTER_TYPE_NUMBER, value = #auth_db.search( true ) },
  45. max_users = { type = FILTER_TYPE_NUMBER, value = get_minetest_config( "max_users" ) },
  46. lifetime = { type = FILTER_TYPE_PERIOD, value = rec and rec.lifetime or 0 },
  47. sessions = { type = FILTER_TYPE_NUMBER, value = rec and rec.total_sessions or 0 },
  48. failures = { type = FILTER_TYPE_NUMBER, value = rec and rec.total_failures or 0 },
  49. attempts = { type = FILTER_TYPE_NUMBER, value = rec and rec.total_attempts or 0 },
  50. owner = { type = FILTER_TYPE_STRING, value = get_minetest_config( "name" ) },
  51. uptime = { type = FILTER_TYPE_PERIOD, value = minetest.get_server_uptime( ) },
  52. oldlogin = { type = FILTER_TYPE_MOMENT, value = rec and rec.oldlogin or 0 },
  53. newlogin = { type = FILTER_TYPE_MOMENT, value = rec and rec.newlogin or 0 },
  54. ip_names_list = { type = FILTER_TYPE_SERIES, value = meta.previous_names or { } },
  55. ip_prelogin = { type = FILTER_TYPE_MOMENT, value = meta.prelogin or 0 },
  56. ip_oldcheck = { type = FILTER_TYPE_MOMENT, value = meta.oldcheck or 0 },
  57. ip_newcheck = { type = FILTER_TYPE_MOMENT, value = meta.newcheck or 0 },
  58. ip_failures = { type = FILTER_TYPE_NUMBER, value = meta.count_failures or 0 },
  59. ip_attempts = { type = FILTER_TYPE_NUMBER, value = meta.count_attempts or 0 }
  60. } )
  61. auth_watchdog.on_attempt( convert_ipv4( player_ip ), player_name )
  62. return res
  63. end )
  64. minetest.register_on_joinplayer( function ( player )
  65. local player_name = player:get_player_name( )
  66. auth_db.on_login_success( player_name, "0.0.0.0" )
  67. auth_db.on_session_opened( player_name )
  68. minetest.after( 0.0, function ( )
  69. -- hack since player status not immediately available on some MT versions
  70. auth_watchdog.on_success( convert_ipv4( minetest.get_player_information( player_name ).address ) )
  71. end )
  72. end )
  73. minetest.register_on_leaveplayer( function ( player )
  74. auth_db.on_session_closed( player:get_player_name( ) )
  75. end )
  76. minetest.register_on_shutdown( function( )
  77. auth_db.disconnect( )
  78. end )
  79. minetest.register_authentication_handler( {
  80. -- translate old auth hooks to new database backend
  81. get_auth = function( username )
  82. local rec = auth_db.select_record( username )
  83. if rec then
  84. local assigned_privs = rec.assigned_privs
  85. if get_minetest_config( "name" ) == username then
  86. -- grant server operator all privileges
  87. -- (TODO: implement as function that honors give_to_admin flag)
  88. assigned_privs = { }
  89. for priv in pairs( core.registered_privileges ) do
  90. table.insert( assigned_privs, priv )
  91. end
  92. end
  93. return { password = rec.password, privileges = unpack_privileges( assigned_privs ), last_login = rec.newlogin }
  94. end
  95. end,
  96. create_auth = function( username, password )
  97. if auth_db.create_record( username, password ) then
  98. auth_db.set_assigned_privs( username, get_default_privs( ) )
  99. minetest.log( "info", "Created player '" .. username .. "' in authentication database" )
  100. end
  101. end,
  102. delete_auth = function( username )
  103. if auth_db.delete_record( username ) then
  104. minetest.log( "info", "Deleted player '" .. username .. "' in authenatication database" )
  105. end
  106. end,
  107. set_password = function ( username, password )
  108. if auth_db.set_password( username, password ) then
  109. minetest.log( "info", "Reset password of player '" .. username .. "' in authentication database" )
  110. end
  111. end,
  112. set_privileges = function ( username, privileges )
  113. -- server operator's privileges are immutable
  114. if get_minetest_config( "name" ) == username then return end
  115. if auth_db.set_assigned_privs( username, pack_privileges( privileges ) ) then
  116. minetest.notify_authentication_modified( username )
  117. minetest.log( "info", "Reset privileges of player '" .. username .. "' in authentication database" )
  118. end
  119. end,
  120. record_login = function ( ) end,
  121. reload = function ( ) end,
  122. iterate = auth_db.records
  123. } )
  124. auth_db.connect( )
  125. __commands( { auth_db = auth_db, auth_filter = auth_filter } )