plugins/mod_saslauth.lua

changeset 282
80e7de32b618
parent 278
770a78cd38d7
parent 281
826308c07627
child 283
8e1fd8ff66ee
equal deleted inserted replaced
280:516f4c901991 282:80e7de32b618
1 1
2 local st = require "util.stanza"; 2 local st = require "util.stanza";
3 local send = require "core.sessionmanager".send_to_session; 3 local send = require "core.sessionmanager".send_to_session;
4 local sm_bind_resource = require "core.sessionmanager".bind_resource; 4 local sm_bind_resource = require "core.sessionmanager".bind_resource;
5 local jid
5 6
6 local usermanager_validate_credentials = require "core.usermanager".validate_credentials; 7 local usermanager_validate_credentials = require "core.usermanager".validate_credentials;
7 local t_concat, t_insert = table.concat, table.insert; 8 local t_concat, t_insert = table.concat, table.insert;
8 local tostring = tostring; 9 local tostring = tostring;
9 10
13 local xmlns_bind ='urn:ietf:params:xml:ns:xmpp-bind'; 14 local xmlns_bind ='urn:ietf:params:xml:ns:xmpp-bind';
14 local xmlns_stanzas ='urn:ietf:params:xml:ns:xmpp-stanzas'; 15 local xmlns_stanzas ='urn:ietf:params:xml:ns:xmpp-stanzas';
15 16
16 local new_sasl = require "util.sasl".new; 17 local new_sasl = require "util.sasl".new;
17 18
18 add_handler("c2s_unauthed", "auth", xmlns_sasl, function (session, stanza) 19 local function build_reply(status, ret)
19 if not session.sasl_handler then 20 local reply = st.stanza(status, {xmlns = xmlns_sasl});
20 session.sasl_handler = new_sasl(stanza.attr.mechanism, 21 if status == "challenge" then
21 function (username, password) 22 reply:text(ret or "");
22 -- onAuth 23 elseif status == "failure" then
23 require "core.usermanager" 24 reply:tag(ret):up();
24 if usermanager_validate_credentials(session.host, username, password) then 25 elseif status == "success" then
25 return true; 26 reply:text(ret or "");
26 end 27 else
27 return false; 28 error("Unknown sasl status: "..status);
28 end, 29 end
29 function (username) 30 return reply;
30 -- onSuccess 31 end
31 local success, err = sessionmanager.make_authenticated(session, username); 32
32 if not success then 33 local function handle_status(session, status)
33 sessionmanager.destroy_session(session); 34 if status == "failure" then
34 return; 35 session.sasl_handler = nil;
35 end 36 elseif status == "success" then
36 session.sasl_handler = nil; 37 session.sasl_handler = nil;
37 session:reset_stream(); 38 session:reset_stream();
38 end, 39 end
39 function (reason) 40 end
40 -- onFail 41
41 log("debug", "SASL failure, reason: %s", reason); 42 local function password_callback(jid, mechanism)
42 end, 43 local node, host = jid_split(jid);
43 function (stanza) 44 local password = (datamanager.load(node, host, "accounts") or {}).password; -- FIXME handle hashed passwords
44 -- onWrite 45 local func = function(x) return x; end;
45 log("debug", "SASL writes: %s", tostring(stanza)); 46 if password then
46 send(session, stanza); 47 if mechanism == "PLAIN" then
48 return func, password;
49 elseif mechanism == "DIGEST-MD5" then
50 return func, require "hashes".md5(node.."::"..password);
51 end
52 end
53 return func, nil;
54 end
55
56 add_handler("c2s_unauthed", "auth", xmlns_sasl,
57 function (session, stanza)
58 if not session.sasl_handler then
59 session.sasl_handler = new_sasl(stanza.attr.mechanism, session.host, password_callback);
60 local status, ret = session.sasl_handler:feed(stanza[1]);
61 handle_status(session, status);
62 session.send(build_reply(status, ret));
63 --[[session.sasl_handler = new_sasl(stanza.attr.mechanism,
64 function (username, password)
65 -- onAuth
66 require "core.usermanager"
67 if usermanager_validate_credentials(session.host, username, password) then
68 return true;
69 end
70 return false;
71 end,
72 function (username)
73 -- onSuccess
74 local success, err = sessionmanager.make_authenticated(session, username);
75 if not success then
76 sessionmanager.destroy_session(session);
77 return;
78 end
79 session.sasl_handler = nil;
80 session:reset_stream();
81 end,
82 function (reason)
83 -- onFail
84 log("debug", "SASL failure, reason: %s", reason);
85 end,
86 function (stanza)
87 -- onWrite
88 log("debug", "SASL writes: %s", tostring(stanza));
89 send(session, stanza);
90 end
91 );
92 session.sasl_handler:feed(stanza); ]]
93 else
94 error("Client tried to negotiate SASL again", 0);
47 end 95 end
48 ); 96 end);
49 session.sasl_handler:feed(stanza);
50 else
51 error("Client tried to negotiate SASL again", 0);
52 end
53 end);
54 97
55 add_handler("c2s_unauthed", "response", xmlns_sasl, function (session, stanza) 98 add_handler("c2s_unauthed", "abort", xmlns_sasl,
56 if session.sasl_handler then 99 function(session, stanza)
57 session.sasl_handler:feed(stanza); 100 if not session.sasl_handler then error("Attempt to abort when sasl has not started"); end
58 end 101 local status, ret = session.sasl_handler:feed(stanza[1]);
59 end); 102 handle_status(session, status);
103 session.send(build_reply(status, ret));
104 end);
105
106 add_handler("c2s_unauthed", "response", xmlns_sasl,
107 function(session, stanza)
108 if not session.sasl_handler then error("Attempt to respond when sasl has not started"); end
109 local status, ret = session.sasl_handler:feed(stanza[1]);
110 handle_status(session, status);
111 session.send(build_reply(status, ret));
112 end);
60 113
61 add_event_hook("stream-features", 114 add_event_hook("stream-features",
62 function (session, features) 115 function (session, features)
63 if not session.username then 116 if not session.username then
64 t_insert(features, "<mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>"); 117 t_insert(features, "<mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>");

mercurial