Software / code / prosody
Comparison
plugins/mod_register.lua @ 7036:f26debcae34e
Merge 0.10->trunk
| author | Kim Alvefur <zash@zash.se> |
|---|---|
| date | Sun, 27 Dec 2015 12:29:28 +0100 |
| parent | 7027:77d838ba91c6 |
| child | 7037:5d52e4ee2ae1 |
comparison
equal
deleted
inserted
replaced
| 7015:17e275e8bd79 | 7036:f26debcae34e |
|---|---|
| 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_set_password = require "core.usermanager".set_password; | 14 local usermanager_set_password = require "core.usermanager".set_password; |
| 15 local usermanager_delete_user = require "core.usermanager".delete_user; | 15 local usermanager_delete_user = require "core.usermanager".delete_user; |
| 16 local os_time = os.time; | |
| 17 local nodeprep = require "util.encodings".stringprep.nodeprep; | 16 local nodeprep = require "util.encodings".stringprep.nodeprep; |
| 18 local jid_bare = require "util.jid".bare; | 17 local jid_bare = require "util.jid".bare; |
| 18 local create_throttle = require "util.throttle".create; | |
| 19 local new_cache = require "util.cache".new; | |
| 19 | 20 |
| 20 local compat = module:get_option_boolean("registration_compat", true); | 21 local compat = module:get_option_boolean("registration_compat", true); |
| 21 local allow_registration = module:get_option_boolean("allow_registration", false); | 22 local allow_registration = module:get_option_boolean("allow_registration", false); |
| 22 local additional_fields = module:get_option("additional_registration_fields", {}); | 23 local additional_fields = module:get_option("additional_registration_fields", {}); |
| 23 | 24 |
| 82 features:add_child(register_stream_feature); | 83 features:add_child(register_stream_feature); |
| 83 end); | 84 end); |
| 84 | 85 |
| 85 local function handle_registration_stanza(event) | 86 local function handle_registration_stanza(event) |
| 86 local session, stanza = event.origin, event.stanza; | 87 local session, stanza = event.origin, event.stanza; |
| 88 local log = session.log or module._log; | |
| 87 | 89 |
| 88 local query = stanza.tags[1]; | 90 local query = stanza.tags[1]; |
| 89 if stanza.attr.type == "get" then | 91 if stanza.attr.type == "get" then |
| 90 local reply = st.reply(stanza); | 92 local reply = st.reply(stanza); |
| 91 reply:tag("query", {xmlns = "jabber:iq:register"}) | 93 reply:tag("query", {xmlns = "jabber:iq:register"}) |
| 95 session.send(reply); | 97 session.send(reply); |
| 96 else -- stanza.attr.type == "set" | 98 else -- stanza.attr.type == "set" |
| 97 if query.tags[1] and query.tags[1].name == "remove" then | 99 if query.tags[1] and query.tags[1].name == "remove" then |
| 98 local username, host = session.username, session.host; | 100 local username, host = session.username, session.host; |
| 99 | 101 |
| 102 -- This one weird trick sends a reply to this stanza before the user is deleted | |
| 100 local old_session_close = session.close; | 103 local old_session_close = session.close; |
| 101 session.close = function(session, ...) | 104 session.close = function(session, ...) |
| 102 session.send(st.reply(stanza)); | 105 session.send(st.reply(stanza)); |
| 103 return old_session_close(session, ...); | 106 return old_session_close(session, ...); |
| 104 end | 107 end |
| 105 | 108 |
| 106 local ok, err = usermanager_delete_user(username, host); | 109 local ok, err = usermanager_delete_user(username, host); |
| 107 | 110 |
| 108 if not ok then | 111 if not ok then |
| 109 module:log("debug", "Removing user account %s@%s failed: %s", username, host, err); | 112 log("debug", "Removing user account %s@%s failed: %s", username, host, err); |
| 110 session.close = old_session_close; | 113 session.close = old_session_close; |
| 111 session.send(st.error_reply(stanza, "cancel", "service-unavailable", err)); | 114 session.send(st.error_reply(stanza, "cancel", "service-unavailable", err)); |
| 112 return true; | 115 return true; |
| 113 end | 116 end |
| 114 | 117 |
| 115 module:log("info", "User removed their account: %s@%s", username, host); | 118 log("info", "User removed their account: %s@%s", username, host); |
| 116 module:fire_event("user-deregistered", { username = username, host = host, source = "mod_register", session = session }); | 119 module:fire_event("user-deregistered", { username = username, host = host, source = "mod_register", session = session }); |
| 117 else | 120 else |
| 118 local username = nodeprep(query:get_child_text("username")); | 121 local username = nodeprep(query:get_child_text("username")); |
| 119 local password = query:get_child_text("password"); | 122 local password = query:get_child_text("password"); |
| 120 if username and password then | 123 if username and password then |
| 167 end | 170 end |
| 168 return data; | 171 return data; |
| 169 end | 172 end |
| 170 end | 173 end |
| 171 | 174 |
| 172 local recent_ips = {}; | |
| 173 local min_seconds_between_registrations = module:get_option_number("min_seconds_between_registrations"); | 175 local min_seconds_between_registrations = module:get_option_number("min_seconds_between_registrations"); |
| 174 local whitelist_only = module:get_option_boolean("whitelist_registration_only"); | 176 local whitelist_only = module:get_option_boolean("whitelist_registration_only"); |
| 175 local whitelisted_ips = module:get_option_set("registration_whitelist", { "127.0.0.1" })._items; | 177 local whitelisted_ips = module:get_option_set("registration_whitelist", { "127.0.0.1" })._items; |
| 176 local blacklisted_ips = module:get_option_set("registration_blacklist", {})._items; | 178 local blacklisted_ips = module:get_option_set("registration_blacklist", {})._items; |
| 177 | 179 |
| 180 local throttle_max = module:get_option_number("registration_throttle_max", min_seconds_between_registrations and 1); | |
| 181 local throttle_period = module:get_option_number("registration_throttle_period", min_seconds_between_registrations); | |
| 182 local throttle_cache_size = module:get_option_number("registration_throttle_cache_size", 100); | |
| 183 local blacklist_overflow = module_get_option_boolean("blacklist_on_registration_throttle_overload", false); | |
| 184 | |
| 185 local throttle_cache = new_cache(throttle_cache_size, blacklist_overflow and function (ip, throttle) | |
| 186 if not throttle:peek() then | |
| 187 module:log("info", "Adding ip %s to registration blacklist", ip); | |
| 188 blacklisted_ips[ip] = true; | |
| 189 end | |
| 190 end); | |
| 191 | |
| 192 local function check_throttle(ip) | |
| 193 if not throttle_max then return true end | |
| 194 local throttle = throttle_cache:get(ip); | |
| 195 if not throttle then | |
| 196 throttle = create_throttle(throttle_max, throttle_period); | |
| 197 end | |
| 198 throttle_cache:set(ip, throttle); | |
| 199 return throttle:poll(1); | |
| 200 end | |
| 201 | |
| 178 module:hook("stanza/iq/jabber:iq:register:query", function(event) | 202 module:hook("stanza/iq/jabber:iq:register:query", function(event) |
| 179 local session, stanza = event.origin, event.stanza; | 203 local session, stanza = event.origin, event.stanza; |
| 204 local log = session.log or module._log; | |
| 180 | 205 |
| 181 if not(allow_registration) or session.type ~= "c2s_unauthed" then | 206 if not(allow_registration) or session.type ~= "c2s_unauthed" then |
| 182 session.send(st.error_reply(stanza, "cancel", "service-unavailable")); | 207 session.send(st.error_reply(stanza, "cancel", "service-unavailable")); |
| 183 else | 208 else |
| 184 local query = stanza.tags[1]; | 209 local query = stanza.tags[1]; |
| 194 if errors then | 219 if errors then |
| 195 session.send(st.error_reply(stanza, "modify", "not-acceptable")); | 220 session.send(st.error_reply(stanza, "modify", "not-acceptable")); |
| 196 else | 221 else |
| 197 -- Check that the user is not blacklisted or registering too often | 222 -- Check that the user is not blacklisted or registering too often |
| 198 if not session.ip then | 223 if not session.ip then |
| 199 module:log("debug", "User's IP not known; can't apply blacklist/whitelist"); | 224 log("debug", "User's IP not known; can't apply blacklist/whitelist"); |
| 200 elseif blacklisted_ips[session.ip] or (whitelist_only and not whitelisted_ips[session.ip]) then | 225 elseif blacklisted_ips[session.ip] or (whitelist_only and not whitelisted_ips[session.ip]) then |
| 201 session.send(st.error_reply(stanza, "cancel", "not-acceptable", "You are not allowed to register an account.")); | 226 session.send(st.error_reply(stanza, "cancel", "not-acceptable", "You are not allowed to register an account.")); |
| 202 return true; | 227 return true; |
| 203 elseif min_seconds_between_registrations and not whitelisted_ips[session.ip] then | 228 elseif min_seconds_between_registrations and not whitelisted_ips[session.ip] then |
| 204 if not recent_ips[session.ip] then | 229 if check_throttle(session.ip) then |
| 205 recent_ips[session.ip] = { time = os_time(), count = 1 }; | 230 session.send(st.error_reply(stanza, "wait", "not-acceptable")); |
| 206 else | 231 return true; |
| 207 local ip = recent_ips[session.ip]; | |
| 208 ip.count = ip.count + 1; | |
| 209 | |
| 210 if os_time() - ip.time < min_seconds_between_registrations then | |
| 211 ip.time = os_time(); | |
| 212 session.send(st.error_reply(stanza, "wait", "not-acceptable")); | |
| 213 return true; | |
| 214 end | |
| 215 ip.time = os_time(); | |
| 216 end | 232 end |
| 217 end | 233 end |
| 218 local username, password = nodeprep(data.username), data.password; | 234 local username, password = nodeprep(data.username), data.password; |
| 219 data.username, data.password = nil, nil; | 235 data.username, data.password = nil, nil; |
| 220 local host = module.host; | 236 local host = module.host; |
| 236 usermanager_delete_user(username, host); | 252 usermanager_delete_user(username, host); |
| 237 session.send(error_reply); | 253 session.send(error_reply); |
| 238 return true; | 254 return true; |
| 239 end | 255 end |
| 240 session.send(st.reply(stanza)); -- user created! | 256 session.send(st.reply(stanza)); -- user created! |
| 241 module:log("info", "User account created: %s@%s", username, host); | 257 log("info", "User account created: %s@%s", username, host); |
| 242 module:fire_event("user-registered", { | 258 module:fire_event("user-registered", { |
| 243 username = username, host = host, source = "mod_register", | 259 username = username, host = host, source = "mod_register", |
| 244 session = session }); | 260 session = session }); |
| 245 else | 261 else |
| 246 session.send(error_reply); | 262 session.send(error_reply); |