comparison plugins/mod_saslauth.lua @ 10411:db2a06b9ff98

Merge 0.11->trunk
author Kim Alvefur <zash@zash.se>
date Sat, 16 Nov 2019 16:52:31 +0100
parents 5c6912289ce3
children 7a3c04789d5c
comparison
equal deleted inserted replaced
10410:659b577f280c 10411:db2a06b9ff98
10 10
11 local st = require "util.stanza"; 11 local st = require "util.stanza";
12 local sm_bind_resource = require "core.sessionmanager".bind_resource; 12 local sm_bind_resource = require "core.sessionmanager".bind_resource;
13 local sm_make_authenticated = require "core.sessionmanager".make_authenticated; 13 local sm_make_authenticated = require "core.sessionmanager".make_authenticated;
14 local base64 = require "util.encodings".base64; 14 local base64 = require "util.encodings".base64;
15 local set = require "util.set";
15 16
16 local usermanager_get_sasl_handler = require "core.usermanager".get_sasl_handler; 17 local usermanager_get_sasl_handler = require "core.usermanager".get_sasl_handler;
17 local tostring = tostring;
18 18
19 local secure_auth_only = module:get_option_boolean("c2s_require_encryption", module:get_option_boolean("require_encryption", false)); 19 local secure_auth_only = module:get_option_boolean("c2s_require_encryption", module:get_option_boolean("require_encryption", false));
20 local allow_unencrypted_plain_auth = module:get_option_boolean("allow_unencrypted_plain_auth", false) 20 local allow_unencrypted_plain_auth = module:get_option_boolean("allow_unencrypted_plain_auth", false)
21 local insecure_mechanisms = module:get_option_set("insecure_sasl_mechanisms", allow_unencrypted_plain_auth and {} or {"PLAIN", "LOGIN"}); 21 local insecure_mechanisms = module:get_option_set("insecure_sasl_mechanisms", allow_unencrypted_plain_auth and {} or {"PLAIN", "LOGIN"});
22 local disabled_mechanisms = module:get_option_set("disable_sasl_mechanisms", { "DIGEST-MD5" }); 22 local disabled_mechanisms = module:get_option_set("disable_sasl_mechanisms", { "DIGEST-MD5" });
65 65
66 local function sasl_process_cdata(session, stanza) 66 local function sasl_process_cdata(session, stanza)
67 local text = stanza[1]; 67 local text = stanza[1];
68 if text then 68 if text then
69 text = base64.decode(text); 69 text = base64.decode(text);
70 --log("debug", "AUTH: %s", text:gsub("[%z\001-\008\011\012\014-\031]", " "));
71 if not text then 70 if not text then
72 session.sasl_handler = nil; 71 session.sasl_handler = nil;
73 session.send(build_reply("failure", "incorrect-encoding")); 72 session.send(build_reply("failure", "incorrect-encoding"));
74 return true; 73 return true;
75 end 74 end
76 end 75 end
77 local status, ret, err_msg = session.sasl_handler:process(text); 76 local status, ret, err_msg = session.sasl_handler:process(text);
78 status, ret, err_msg = handle_status(session, status, ret, err_msg); 77 status, ret, err_msg = handle_status(session, status, ret, err_msg);
79 local s = build_reply(status, ret, err_msg); 78 local s = build_reply(status, ret, err_msg);
80 log("debug", "sasl reply: %s", tostring(s));
81 session.send(s); 79 session.send(s);
82 return true; 80 return true;
83 end 81 end
84 82
85 module:hook_tag(xmlns_sasl, "success", function (session) 83 module:hook_tag(xmlns_sasl, "success", function (session)
246 return; 244 return;
247 end 245 end
248 local sasl_handler = usermanager_get_sasl_handler(module.host, origin) 246 local sasl_handler = usermanager_get_sasl_handler(module.host, origin)
249 origin.sasl_handler = sasl_handler; 247 origin.sasl_handler = sasl_handler;
250 if origin.encrypted then 248 if origin.encrypted then
251 -- check wether LuaSec has the nifty binding to the function needed for tls-unique 249 -- check whether LuaSec has the nifty binding to the function needed for tls-unique
252 -- FIXME: would be nice to have this check only once and not for every socket 250 -- FIXME: would be nice to have this check only once and not for every socket
253 if sasl_handler.add_cb_handler then 251 if sasl_handler.add_cb_handler then
254 local socket = origin.conn:socket(); 252 local socket = origin.conn:socket();
255 if socket.getpeerfinished then 253 if socket.getpeerfinished then
254 log("debug", "Channel binding 'tls-unique' supported");
256 sasl_handler:add_cb_handler("tls-unique", tls_unique); 255 sasl_handler:add_cb_handler("tls-unique", tls_unique);
256 else
257 log("debug", "Channel binding 'tls-unique' not supported (by LuaSec?)");
257 end 258 end
258 sasl_handler["userdata"] = { 259 sasl_handler["userdata"] = {
259 ["tls-unique"] = socket; 260 ["tls-unique"] = socket;
260 }; 261 };
262 else
263 log("debug", "Channel binding not supported by SASL handler");
261 end 264 end
262 end 265 end
263 local mechanisms = st.stanza("mechanisms", mechanisms_attr); 266 local mechanisms = st.stanza("mechanisms", mechanisms_attr);
264 local sasl_mechanisms = sasl_handler:mechanisms() 267 local sasl_mechanisms = sasl_handler:mechanisms()
268 local available_mechanisms = set.new();
265 for mechanism in pairs(sasl_mechanisms) do 269 for mechanism in pairs(sasl_mechanisms) do
266 if disabled_mechanisms:contains(mechanism) then 270 available_mechanisms:add(mechanism);
267 log("debug", "Not offering disabled mechanism %s", mechanism); 271 end
268 elseif not origin.secure and insecure_mechanisms:contains(mechanism) then 272 log("debug", "SASL mechanisms supported by handler: %s", available_mechanisms);
269 log("debug", "Not offering mechanism %s on insecure connection", mechanism); 273
270 else 274 local usable_mechanisms = available_mechanisms - disabled_mechanisms;
271 log("debug", "Offering mechanism %s", mechanism); 275
276 local available_disabled = set.intersection(available_mechanisms, disabled_mechanisms);
277 if not available_disabled:empty() then
278 log("debug", "Not offering disabled mechanisms: %s", available_disabled);
279 end
280
281 local available_insecure = set.intersection(available_mechanisms, insecure_mechanisms);
282 if not origin.secure and not available_insecure:empty() then
283 log("debug", "Session is not secure, not offering insecure mechanisms: %s", available_insecure);
284 usable_mechanisms = usable_mechanisms - insecure_mechanisms;
285 end
286
287 if not usable_mechanisms:empty() then
288 log("debug", "Offering usable mechanisms: %s", usable_mechanisms);
289 for mechanism in available_mechanisms do
272 mechanisms:tag("mechanism"):text(mechanism):up(); 290 mechanisms:tag("mechanism"):text(mechanism):up();
273 end 291 end
274 end
275 if mechanisms[1] then
276 features:add_child(mechanisms); 292 features:add_child(mechanisms);
277 elseif not next(sasl_mechanisms) then 293 return;
278 log("warn", "No available SASL mechanisms, verify that the configured authentication module is working"); 294 end
279 else 295
280 log("warn", "All available authentication mechanisms are either disabled or not suitable for an insecure connection"); 296 local authmod = module:get_option_string("authentication", "internal_plain");
281 end 297 if available_mechanisms:empty() then
298 log("warn", "No available SASL mechanisms, verify that the configured authentication module '%s' is loaded and configured correctly", authmod);
299 return;
300 end
301
302 if not origin.secure and not available_insecure:empty() then
303 if not available_disabled:empty() then
304 log("warn", "All SASL mechanisms provided by authentication module '%s' are forbidden on insecure connections (%s) or disabled (%s)",
305 authmod, available_insecure, available_disabled);
306 else
307 log("warn", "All SASL mechanisms provided by authentication module '%s' are forbidden on insecure connections (%s)",
308 authmod, available_insecure);
309 end
310 elseif not available_disabled:empty() then
311 log("warn", "All SASL mechanisms provided by authentication module '%s' are disabled (%s)",
312 authmod, available_disabled);
313 end
314
282 else 315 else
283 features:tag("bind", bind_attr):tag("required"):up():up(); 316 features:tag("bind", bind_attr):tag("required"):up():up();
284 features:tag("session", xmpp_session_attr):tag("optional"):up():up(); 317 features:tag("session", xmpp_session_attr):tag("optional"):up():up();
285 end 318 end
286 end); 319 end);