plugins/mod_register.lua

changeset 3529
3f9cc12308aa
parent 3394
9bf5f2b3314b
child 3540
bc139431830b
equal deleted inserted replaced
3528:5cdcd7ee6ef5 3529:3f9cc12308aa
16 local os_time = os.time; 16 local os_time = os.time;
17 local nodeprep = require "util.encodings".stringprep.nodeprep; 17 local nodeprep = require "util.encodings".stringprep.nodeprep;
18 18
19 module:add_feature("jabber:iq:register"); 19 module:add_feature("jabber:iq:register");
20 20
21 module:add_iq_handler("c2s", "jabber:iq:register", function (session, stanza) 21 module:hook("iq/self/jabber:iq:register:query", function(event)
22 if stanza.tags[1].name == "query" then 22 local session, stanza = event.origin, event.stanza;
23 local query = stanza.tags[1]; 23
24 if stanza.attr.type == "get" then 24 local query = stanza.tags[1];
25 local reply = st.reply(stanza); 25 if stanza.attr.type == "get" then
26 reply:tag("query", {xmlns = "jabber:iq:register"}) 26 local reply = st.reply(stanza);
27 :tag("registered"):up() 27 reply:tag("query", {xmlns = "jabber:iq:register"})
28 :tag("username"):text(session.username):up() 28 :tag("registered"):up()
29 :tag("password"):up(); 29 :tag("username"):text(session.username):up()
30 session.send(reply); 30 :tag("password"):up();
31 elseif stanza.attr.type == "set" then 31 session.send(reply);
32 if query.tags[1] and query.tags[1].name == "remove" then 32 else -- stanza.attr.type == "set"
33 -- TODO delete user auth data, send iq response, kick all user resources with a <not-authorized/>, delete all user data 33 if query.tags[1] and query.tags[1].name == "remove" then
34 local username, host = session.username, session.host; 34 -- TODO delete user auth data, send iq response, kick all user resources with a <not-authorized/>, delete all user data
35 --session.send(st.error_reply(stanza, "cancel", "not-allowed")); 35 local username, host = session.username, session.host;
36 --return; 36 --session.send(st.error_reply(stanza, "cancel", "not-allowed"));
37 usermanager_set_password(username, nil, host); -- Disable account 37 --return;
38 -- FIXME the disabling currently allows a different user to recreate the account 38 usermanager_set_password(username, nil, host); -- Disable account
39 -- we should add an in-memory account block mode when we have threading 39 -- FIXME the disabling currently allows a different user to recreate the account
40 session.send(st.reply(stanza)); 40 -- we should add an in-memory account block mode when we have threading
41 local roster = session.roster; 41 session.send(st.reply(stanza));
42 for _, session in pairs(hosts[host].sessions[username].sessions) do -- disconnect all resources 42 local roster = session.roster;
43 session:close({condition = "not-authorized", text = "Account deleted"}); 43 for _, session in pairs(hosts[host].sessions[username].sessions) do -- disconnect all resources
44 end 44 session:close({condition = "not-authorized", text = "Account deleted"});
45 -- TODO datamanager should be able to delete all user data itself 45 end
46 datamanager.store(username, host, "vcard", nil); 46 -- TODO datamanager should be able to delete all user data itself
47 datamanager.store(username, host, "private", nil); 47 datamanager.store(username, host, "vcard", nil);
48 datamanager.list_store(username, host, "offline", nil); 48 datamanager.store(username, host, "private", nil);
49 local bare = username.."@"..host; 49 datamanager.list_store(username, host, "offline", nil);
50 for jid, item in pairs(roster) do 50 local bare = username.."@"..host;
51 if jid and jid ~= "pending" then 51 for jid, item in pairs(roster) do
52 if item.subscription == "both" or item.subscription == "from" or (roster.pending and roster.pending[jid]) then 52 if jid and jid ~= "pending" then
53 core_post_stanza(hosts[host], st.presence({type="unsubscribed", from=bare, to=jid})); 53 if item.subscription == "both" or item.subscription == "from" or (roster.pending and roster.pending[jid]) then
54 end 54 core_post_stanza(hosts[host], st.presence({type="unsubscribed", from=bare, to=jid}));
55 if item.subscription == "both" or item.subscription == "to" or item.ask then 55 end
56 core_post_stanza(hosts[host], st.presence({type="unsubscribe", from=bare, to=jid})); 56 if item.subscription == "both" or item.subscription == "to" or item.ask then
57 end 57 core_post_stanza(hosts[host], st.presence({type="unsubscribe", from=bare, to=jid}));
58 end 58 end
59 end 59 end
60 datamanager.store(username, host, "roster", nil); 60 end
61 datamanager.store(username, host, "privacy", nil); 61 datamanager.store(username, host, "roster", nil);
62 datamanager.store(username, host, "accounts", nil); -- delete accounts datastore at the end 62 datamanager.store(username, host, "privacy", nil);
63 module:log("info", "User removed their account: %s@%s", username, host); 63 datamanager.store(username, host, "accounts", nil); -- delete accounts datastore at the end
64 module:fire_event("user-deregistered", { username = username, host = host, source = "mod_register", session = session }); 64 module:log("info", "User removed their account: %s@%s", username, host);
65 else 65 module:fire_event("user-deregistered", { username = username, host = host, source = "mod_register", session = session });
66 local username = query:child_with_name("username"); 66 else
67 local password = query:child_with_name("password"); 67 local username = query:child_with_name("username");
68 if username and password then 68 local password = query:child_with_name("password");
69 -- FIXME shouldn't use table.concat 69 if username and password then
70 username = nodeprep(table.concat(username)); 70 -- FIXME shouldn't use table.concat
71 password = table.concat(password); 71 username = nodeprep(table.concat(username));
72 if username == session.username then 72 password = table.concat(password);
73 if usermanager_set_password(username, password, session.host) then 73 if username == session.username then
74 session.send(st.reply(stanza)); 74 if usermanager_set_password(username, password, session.host) then
75 else 75 session.send(st.reply(stanza));
76 -- TODO unable to write file, file may be locked, etc, what's the correct error?
77 session.send(st.error_reply(stanza, "wait", "internal-server-error"));
78 end
79 else 76 else
80 session.send(st.error_reply(stanza, "modify", "bad-request")); 77 -- TODO unable to write file, file may be locked, etc, what's the correct error?
78 session.send(st.error_reply(stanza, "wait", "internal-server-error"));
81 end 79 end
82 else 80 else
83 session.send(st.error_reply(stanza, "modify", "bad-request")); 81 session.send(st.error_reply(stanza, "modify", "bad-request"));
84 end 82 end
83 else
84 session.send(st.error_reply(stanza, "modify", "bad-request"));
85 end 85 end
86 end 86 end
87 else 87 end
88 session.send(st.error_reply(stanza, "cancel", "service-unavailable")); 88 return true;
89 end;
90 end); 89 end);
91 90
92 local recent_ips = {}; 91 local recent_ips = {};
93 local min_seconds_between_registrations = module:get_option("min_seconds_between_registrations"); 92 local min_seconds_between_registrations = module:get_option("min_seconds_between_registrations");
94 local whitelist_only = module:get_option("whitelist_registration_only"); 93 local whitelist_only = module:get_option("whitelist_registration_only");
96 local blacklisted_ips = module:get_option("registration_blacklist") or {}; 95 local blacklisted_ips = module:get_option("registration_blacklist") or {};
97 96
98 for _, ip in ipairs(whitelisted_ips) do whitelisted_ips[ip] = true; end 97 for _, ip in ipairs(whitelisted_ips) do whitelisted_ips[ip] = true; end
99 for _, ip in ipairs(blacklisted_ips) do blacklisted_ips[ip] = true; end 98 for _, ip in ipairs(blacklisted_ips) do blacklisted_ips[ip] = true; end
100 99
101 module:add_iq_handler("c2s_unauthed", "jabber:iq:register", function (session, stanza) 100 module:hook("stanza/iq/jabber:iq:register:query", function(event)
102 if module:get_option("allow_registration") == false then 101 local session, stanza = event.origin, event.stanza;
102
103 if module:get_option("allow_registration") == false or session.type ~= "c2s_unauthed" then
103 session.send(st.error_reply(stanza, "cancel", "service-unavailable")); 104 session.send(st.error_reply(stanza, "cancel", "service-unavailable"));
104 elseif stanza.tags[1].name == "query" then 105 else
105 local query = stanza.tags[1]; 106 local query = stanza.tags[1];
106 if stanza.attr.type == "get" then 107 if stanza.attr.type == "get" then
107 local reply = st.reply(stanza); 108 local reply = st.reply(stanza);
108 reply:tag("query", {xmlns = "jabber:iq:register"}) 109 reply:tag("query", {xmlns = "jabber:iq:register"})
109 :tag("instructions"):text("Choose a username and password for use with this service."):up() 110 :tag("instructions"):text("Choose a username and password for use with this service."):up()
120 -- Check that the user is not blacklisted or registering too often 121 -- Check that the user is not blacklisted or registering too often
121 if not session.ip then 122 if not session.ip then
122 module:log("debug", "User's IP not known; can't apply blacklist/whitelist"); 123 module:log("debug", "User's IP not known; can't apply blacklist/whitelist");
123 elseif blacklisted_ips[session.ip] or (whitelist_only and not whitelisted_ips[session.ip]) then 124 elseif blacklisted_ips[session.ip] or (whitelist_only and not whitelisted_ips[session.ip]) then
124 session.send(st.error_reply(stanza, "cancel", "not-acceptable", "You are not allowed to register an account.")); 125 session.send(st.error_reply(stanza, "cancel", "not-acceptable", "You are not allowed to register an account."));
125 return; 126 return true;
126 elseif min_seconds_between_registrations and not whitelisted_ips[session.ip] then 127 elseif min_seconds_between_registrations and not whitelisted_ips[session.ip] then
127 if not recent_ips[session.ip] then 128 if not recent_ips[session.ip] then
128 recent_ips[session.ip] = { time = os_time(), count = 1 }; 129 recent_ips[session.ip] = { time = os_time(), count = 1 };
129 else 130 else
130 local ip = recent_ips[session.ip]; 131 local ip = recent_ips[session.ip];
131 ip.count = ip.count + 1; 132 ip.count = ip.count + 1;
132 133
133 if os_time() - ip.time < min_seconds_between_registrations then 134 if os_time() - ip.time < min_seconds_between_registrations then
134 ip.time = os_time(); 135 ip.time = os_time();
135 session.send(st.error_reply(stanza, "wait", "not-acceptable")); 136 session.send(st.error_reply(stanza, "wait", "not-acceptable"));
136 return; 137 return true;
137 end 138 end
138 ip.time = os_time(); 139 ip.time = os_time();
139 end 140 end
140 end 141 end
141 -- FIXME shouldn't use table.concat 142 -- FIXME shouldn't use table.concat
161 else 162 else
162 session.send(st.error_reply(stanza, "modify", "not-acceptable")); 163 session.send(st.error_reply(stanza, "modify", "not-acceptable"));
163 end 164 end
164 end 165 end
165 end 166 end
166 else 167 end
167 session.send(st.error_reply(stanza, "cancel", "service-unavailable")); 168 return true;
168 end;
169 end); 169 end);
170 170

mercurial