init.lua 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. --------------------------------------------------------
  2. -- Minetest :: Auth Redux Mod v2.13 (auth_rx)
  3. --
  4. -- See README.txt for licensing and release notes.
  5. -- Copyright (c) 2017-2018, Leslie E. Krause
  6. --------------------------------------------------------
  7. local world_path = minetest.get_worldpath( )
  8. local mod_name = minetest.get_current_modname() or "auth_rx"
  9. local mod_path = minetest.get_modpath( mod_name )
  10. dofile( mod_path .. "/helpers.lua" )
  11. dofile( mod_path .. "/filter.lua" )
  12. dofile( mod_path .. "/db.lua" )
  13. dofile( mod_path .. "/watchdog.lua" )
  14. local __commands = dofile( mod_path .. "/commands.lua" )
  15. AuthInitFile( world_path, "auth.db" )
  16. -----------------------------------------------------
  17. -- Registered Authentication Handler
  18. -----------------------------------------------------
  19. local auth_filter = AuthFilter( world_path, "greenlist.mt" )
  20. local auth_db = AuthDatabase( world_path, "auth.db" )
  21. local auth_watchdog = AuthWatchdog( )
  22. local is_50 = minetest.has_feature("object_use_texture_alpha")
  23. local is_54 = minetest.has_feature("direct_velocity_on_players")
  24. if is_50 then
  25. if minetest.register_on_auth_fail then
  26. minetest.register_on_auth_fail( function ( player_name, player_ip )
  27. auth_db.on_login_failure( player_name, player_ip )
  28. auth_watchdog.on_failure( convert_ipv4( player_ip ) )
  29. end )
  30. end
  31. end
  32. if is_54 then
  33. if minetest.register_on_authplayer then
  34. minetest.register_on_authplayer( function ( player_name, player_ip, is_success )
  35. if is_success then
  36. return
  37. end
  38. auth_db.on_login_failure( player_name, player_ip )
  39. auth_watchdog.on_failure( convert_ipv4( player_ip ) )
  40. end )
  41. end
  42. end
  43. minetest.register_on_prejoinplayer( function ( player_name, player_ip )
  44. local rec = auth_db.select_record( player_name )
  45. local meta = auth_watchdog.get_metadata( convert_ipv4( player_ip ) )
  46. if rec then
  47. auth_db.on_login_attempt( player_name, player_ip )
  48. else
  49. -- prevent creation of case-insensitive duplicate accounts
  50. local uname = string.lower( player_name )
  51. for cname in auth_db.records( ) do
  52. if string.lower( cname ) == uname then
  53. return string.format( "A player named %s already exists on this server.", cname )
  54. end
  55. end
  56. end
  57. local res = auth_filter.is_enabled and auth_filter.process( {
  58. name = { type = FILTER_TYPE_STRING, value = player_name },
  59. addr = { type = FILTER_TYPE_ADDRESS, value = convert_ipv4( player_ip ) },
  60. is_new = { type = FILTER_TYPE_BOOLEAN, value = rec == nil },
  61. privs_list = { type = FILTER_TYPE_SERIES, value = rec and rec.assigned_privs or { } },
  62. users_list = { type = FILTER_TYPE_SERIES, value = auth_db.search( true ) },
  63. cur_users = { type = FILTER_TYPE_NUMBER, value = #auth_db.search( true ) },
  64. max_users = { type = FILTER_TYPE_NUMBER, value = get_minetest_config( "max_users" ) },
  65. lifetime = { type = FILTER_TYPE_PERIOD, value = rec and rec.lifetime or 0 },
  66. sessions = { type = FILTER_TYPE_NUMBER, value = rec and rec.total_sessions or 0 },
  67. failures = { type = FILTER_TYPE_NUMBER, value = rec and rec.total_failures or 0 },
  68. attempts = { type = FILTER_TYPE_NUMBER, value = rec and rec.total_attempts or 0 },
  69. owner = { type = FILTER_TYPE_STRING, value = get_minetest_config( "name" ) },
  70. uptime = { type = FILTER_TYPE_PERIOD, value = minetest.get_server_uptime( ) },
  71. oldlogin = { type = FILTER_TYPE_MOMENT, value = rec and rec.oldlogin or 0 },
  72. newlogin = { type = FILTER_TYPE_MOMENT, value = rec and rec.newlogin or 0 },
  73. ip_names_list = { type = FILTER_TYPE_SERIES, value = meta.previous_names or { } },
  74. ip_prelogin = { type = FILTER_TYPE_MOMENT, value = meta.prelogin or 0 },
  75. ip_oldcheck = { type = FILTER_TYPE_MOMENT, value = meta.oldcheck or 0 },
  76. ip_newcheck = { type = FILTER_TYPE_MOMENT, value = meta.newcheck or 0 },
  77. ip_failures = { type = FILTER_TYPE_NUMBER, value = meta.count_failures or 0 },
  78. ip_attempts = { type = FILTER_TYPE_NUMBER, value = meta.count_attempts or 0 }
  79. }, true ) or nil
  80. auth_watchdog.on_attempt( convert_ipv4( player_ip ), player_name )
  81. return res
  82. end )
  83. minetest.register_on_joinplayer( function ( player )
  84. local player_name
  85. local player_oj
  86. local player_ip
  87. if player ~= nil then
  88. player_name = player:get_player_name( )
  89. player_oj = minetest.get_player_information( player_name )
  90. player_ip = player_oj.address -- this doesn't work in singleplayer!
  91. auth_db.on_login_success( player_name, player_ip )
  92. auth_db.on_session_opened( player_name )
  93. auth_watchdog.on_success( convert_ipv4( player_ip ) )
  94. minetest.log( "warning", "[auth_rx] in authentication database players success joined ".. player_name )
  95. else
  96. minetest.log( "error", "[auth_rx] incomplete auth process on player obj nil ip obj address" )
  97. end
  98. end )
  99. minetest.register_on_leaveplayer( function ( player )
  100. local name
  101. if player ~= nil then
  102. name = player:get_player_name( )
  103. auth_db.on_session_closed( name )
  104. minetest.log( "warning", "[auth_rx] player "..name.." leaving" )
  105. else
  106. minetest.log( "error", "[auth_rx] incomplete player leaving without writing in dbx due nil object" )
  107. end
  108. end )
  109. minetest.register_on_shutdown( function( )
  110. auth_db.disconnect( )
  111. end )
  112. minetest.register_authentication_handler( {
  113. -- translate old auth hooks to new database backend
  114. get_auth = function( username )
  115. minetest.log( "verbose" , "[auth_rx] get_auth handler access to some resource for " .. username )
  116. local rec = auth_db.select_record( username )
  117. if rec then
  118. local assigned_privs = rec.assigned_privs
  119. if get_minetest_config( "name" ) == username then
  120. -- grant server operator all privileges
  121. assigned_privs = { }
  122. for priv in pairs( minetest.registered_privileges ) do
  123. table.insert( assigned_privs, priv )
  124. end
  125. end
  126. return { password = rec.password, privileges = unpack_privileges( assigned_privs ), last_login = rec.newlogin }
  127. end
  128. end,
  129. create_auth = function( username, password )
  130. minetest.log( "verbose" , "[auth_rx] create_auth handler new user over server for " .. username )
  131. local rec = auth_db.create_record( username, password )
  132. if rec then
  133. local assigned_privs = get_default_privs( )
  134. if get_minetest_config( "name" ) == username then
  135. -- grant server operator all privileges
  136. assigned_privs = { }
  137. for priv in pairs( minetest.registered_privileges ) do
  138. table.insert( assigned_privs, priv )
  139. end
  140. end
  141. auth_db.set_assigned_privs( username, assigned_privs )
  142. end
  143. end,
  144. delete_auth = function( username )
  145. minetest.log( "verbose" , "[auth_rx] delete_auth handler for " .. username )
  146. -- server operator's privileges are immutable
  147. if get_minetest_config( "name" ) ~= username then
  148. local rec = auth_db.delete_record( username )
  149. if rec then
  150. minetest.log( "info", "Deleted player '" .. username .. "' in authenatication database" )
  151. end
  152. end
  153. end,
  154. set_password = function ( username, password )
  155. minetest.log( "verbose" , "[auth_rx] set_password handler for " .. username )
  156. local rec = auth_db.set_password( username, password )
  157. if rec then
  158. minetest.log( "info", "Reset password of player '" .. username .. "' in authentication database" )
  159. end
  160. end,
  161. set_privileges = function ( username, privileges )
  162. minetest.log( "verbose" , "[auth_rx] set_privileges handler grants for " .. username )
  163. local assigned_privs = pack_privileges( privileges )
  164. -- server operator's privileges are immutable
  165. if get_minetest_config( "name" ) == username then
  166. assigned_privs = { }
  167. for priv in pairs( minetest.registered_privileges ) do
  168. table.insert( assigned_privs, priv )
  169. end
  170. end
  171. if auth_db.set_assigned_privs( username, assigned_privs ) then
  172. minetest.notify_authentication_modified( username )
  173. end
  174. end,
  175. record_login = function ( ) end,
  176. reload = function ( ) end,
  177. iterate = auth_db.records
  178. } )
  179. auth_db.connect( )
  180. auth_filter.is_enabled = true
  181. __commands( { auth_db = auth_db, auth_filter = auth_filter } )
  182. print("[auth_rx] mod authentication database loaded" )