Software / code / prosody
Comparison
plugins/mod_register_ibr.lua @ 8485:0e02c6de5c02
mod_register_ibr: Split out throttling and IP limitations into mod_register_limits (#723)
| author | Kim Alvefur <zash@zash.se> |
|---|---|
| date | Sat, 09 Dec 2017 19:35:08 +0100 |
| parent | 8484:f591855f060d |
| child | 8488:95706e0f19fc |
comparison
equal
deleted
inserted
replaced
| 8484:f591855f060d | 8485:0e02c6de5c02 |
|---|---|
| 11 local dataform_new = require "util.dataforms".new; | 11 local dataform_new = require "util.dataforms".new; |
| 12 local usermanager_user_exists = require "core.usermanager".user_exists; | 12 local usermanager_user_exists = require "core.usermanager".user_exists; |
| 13 local usermanager_create_user = require "core.usermanager".create_user; | 13 local usermanager_create_user = require "core.usermanager".create_user; |
| 14 local usermanager_delete_user = require "core.usermanager".delete_user; | 14 local usermanager_delete_user = require "core.usermanager".delete_user; |
| 15 local nodeprep = require "util.encodings".stringprep.nodeprep; | 15 local nodeprep = require "util.encodings".stringprep.nodeprep; |
| 16 local create_throttle = require "util.throttle".create; | |
| 17 local new_cache = require "util.cache".new; | |
| 18 local ip_util = require "util.ip"; | |
| 19 local new_ip = ip_util.new_ip; | |
| 20 local match_ip = ip_util.match; | |
| 21 local parse_cidr = ip_util.parse_cidr; | |
| 22 | 16 |
| 23 local additional_fields = module:get_option("additional_registration_fields", {}); | 17 local additional_fields = module:get_option("additional_registration_fields", {}); |
| 24 local require_encryption = module:get_option_boolean("c2s_require_encryption", | 18 local require_encryption = module:get_option_boolean("c2s_require_encryption", |
| 25 module:get_option_boolean("require_encryption", false)); | 19 module:get_option_boolean("require_encryption", false)); |
| 26 | 20 |
| 111 end | 105 end |
| 112 return data; | 106 return data; |
| 113 end | 107 end |
| 114 end | 108 end |
| 115 | 109 |
| 116 local min_seconds_between_registrations = module:get_option_number("min_seconds_between_registrations"); | |
| 117 local whitelist_only = module:get_option_boolean("whitelist_registration_only"); | |
| 118 local whitelisted_ips = module:get_option_set("registration_whitelist", { "127.0.0.1", "::1" })._items; | |
| 119 local blacklisted_ips = module:get_option_set("registration_blacklist", {})._items; | |
| 120 | |
| 121 local throttle_max = module:get_option_number("registration_throttle_max", min_seconds_between_registrations and 1); | |
| 122 local throttle_period = module:get_option_number("registration_throttle_period", min_seconds_between_registrations); | |
| 123 local throttle_cache_size = module:get_option_number("registration_throttle_cache_size", 100); | |
| 124 local blacklist_overflow = module:get_option_boolean("blacklist_on_registration_throttle_overload", false); | |
| 125 | |
| 126 local throttle_cache = new_cache(throttle_cache_size, blacklist_overflow and function (ip, throttle) | |
| 127 if not throttle:peek() then | |
| 128 module:log("info", "Adding ip %s to registration blacklist", ip); | |
| 129 blacklisted_ips[ip] = true; | |
| 130 end | |
| 131 end or nil); | |
| 132 | |
| 133 local function check_throttle(ip) | |
| 134 if not throttle_max then return true end | |
| 135 local throttle = throttle_cache:get(ip); | |
| 136 if not throttle then | |
| 137 throttle = create_throttle(throttle_max, throttle_period); | |
| 138 end | |
| 139 throttle_cache:set(ip, throttle); | |
| 140 return throttle:poll(1); | |
| 141 end | |
| 142 | |
| 143 local function ip_in_set(set, ip) | |
| 144 if set[ip] then | |
| 145 return true; | |
| 146 end | |
| 147 ip = new_ip(ip); | |
| 148 for in_set in pairs(set) do | |
| 149 if match_ip(ip, parse_cidr(in_set)) then | |
| 150 return true; | |
| 151 end | |
| 152 end | |
| 153 return false; | |
| 154 end | |
| 155 | |
| 156 -- In-band registration | 110 -- In-band registration |
| 157 module:hook("stanza/iq/jabber:iq:register:query", function(event) | 111 module:hook("stanza/iq/jabber:iq:register:query", function(event) |
| 158 local session, stanza = event.origin, event.stanza; | 112 local session, stanza = event.origin, event.stanza; |
| 159 local log = session.log or module._log; | 113 local log = session.log or module._log; |
| 160 | 114 |
| 179 for field, err in pairs(errors) do | 133 for field, err in pairs(errors) do |
| 180 log("debug", "Field %q: %s", field, err); | 134 log("debug", "Field %q: %s", field, err); |
| 181 end | 135 end |
| 182 session.send(st.error_reply(stanza, "modify", "not-acceptable")); | 136 session.send(st.error_reply(stanza, "modify", "not-acceptable")); |
| 183 else | 137 else |
| 184 -- Check that the user is not blacklisted or registering too often | |
| 185 if not session.ip then | |
| 186 log("debug", "User's IP not known; can't apply blacklist/whitelist"); | |
| 187 elseif ip_in_set(blacklisted_ips, session.ip) or (whitelist_only and not ip_in_set(whitelisted_ips, session.ip)) then | |
| 188 session.send(st.error_reply(stanza, "cancel", "not-acceptable", "You are not allowed to register an account.")); | |
| 189 return true; | |
| 190 elseif throttle_max and not ip_in_set(whitelisted_ips, session.ip) then | |
| 191 if not check_throttle(session.ip) then | |
| 192 log("debug", "Registrations over limit for ip %s", session.ip or "?"); | |
| 193 session.send(st.error_reply(stanza, "wait", "not-acceptable")); | |
| 194 return true; | |
| 195 end | |
| 196 end | |
| 197 local username, password = nodeprep(data.username), data.password; | 138 local username, password = nodeprep(data.username), data.password; |
| 198 data.username, data.password = nil, nil; | 139 data.username, data.password = nil, nil; |
| 199 local host = module.host; | 140 local host = module.host; |
| 200 if not username or username == "" then | 141 if not username or username == "" then |
| 201 log("debug", "The requested username is invalid."); | 142 log("debug", "The requested username is invalid."); |