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'>"); |