TLS/SASL no longer should include the connhandler module
[prosody.git] / plugins / mod_saslauth.lua
1
2 local st = require "util.stanza";
3 local send = require "core.sessionmanager".send_to_session;
4 local sm_bind_resource = require "core.sessionmanager".bind_resource;
5
6 local usermanager_validate_credentials = require "core.usermanager".validate_credentials;
7 local t_concat, t_insert = table.concat, table.insert;
8 local tostring = tostring;
9
10 local log = require "util.logger".init("mod_saslauth");
11
12 local xmlns_sasl ='urn:ietf:params:xml:ns:xmpp-sasl';
13 local xmlns_bind ='urn:ietf:params:xml:ns:xmpp-bind';
14 local xmlns_stanzas ='urn:ietf:params:xml:ns:xmpp-stanzas';
15
16 local new_sasl = require "util.sasl".new;
17
18 add_handler("c2s_unauthed", "auth", xmlns_sasl,
19                 function (session, stanza)
20                         if not session.sasl_handler then
21                                 session.sasl_handler = new_sasl(stanza.attr.mechanism, 
22                                         function (username, password)
23                                                 -- onAuth
24                                                 require "core.usermanager"
25                                                 if usermanager_validate_credentials(session.host, username, password) then
26                                                         return true;
27                                                 end
28                                                 return false;
29                                         end,
30                                         function (username)
31                                                 -- onSuccess
32                                                 local success, err = sessionmanager.make_authenticated(session, username);
33                                                 if not success then
34                                                         sessionmanager.destroy_session(session);
35                                                         return;
36                                                 end
37                                                 session.sasl_handler = nil;
38                                                 session:reset_stream();
39                                         end,
40                                         function (reason)
41                                                 -- onFail
42                                                 log("debug", "SASL failure, reason: %s", reason);
43                                         end,
44                                         function (stanza)
45                                                 -- onWrite
46                                                 log("debug", "SASL writes: %s", tostring(stanza));
47                                                 send(session, stanza);
48                                         end
49                                 );
50                                 session.sasl_handler:feed(stanza);      
51                         else
52                                 error("Client tried to negotiate SASL again", 0);
53                         end
54                         
55                 end);
56                 
57 add_event_hook("stream-features", 
58                                         function (session, features)                                                                                            
59                                                 if not session.username then
60                                                         t_insert(features, "<mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>");
61                                                                 t_insert(features, "<mechanism>PLAIN</mechanism>");
62                                                         t_insert(features, "</mechanisms>");
63                                                 else
64                                                         t_insert(features, "<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'><required/></bind>");
65                                                         t_insert(features, "<session xmlns='urn:ietf:params:xml:ns:xmpp-session'/>");
66                                                 end
67                                                 --send [[<register xmlns="http://jabber.org/features/iq-register"/> ]]
68                                         end);
69                                         
70 add_iq_handler("c2s", "urn:ietf:params:xml:ns:xmpp-bind", 
71                 function (session, stanza)
72                         log("debug", "Client tried to bind to a resource");
73                         local resource;
74                         if stanza.attr.type == "set" then
75                                 local bind = stanza.tags[1];
76                                 
77                                 if bind and bind.attr.xmlns == xmlns_bind then
78                                         resource = bind:child_with_name("resource");
79                                         if resource then
80                                                 resource = resource[1];
81                                         end
82                                 end
83                         end
84                         local success, err = sm_bind_resource(session, resource);
85                         if not success then
86                                 local reply = st.reply(stanza);
87                                 reply.attr.type = "error";
88                                 if err == "conflict" then
89                                         reply:tag("error", { type = "modify" })
90                                                 :tag("conflict", { xmlns = xmlns_stanzas });
91                                 elseif err == "constraint" then
92                                         reply:tag("error", { type = "cancel" })
93                                                 :tag("resource-constraint", { xmlns = xmlns_stanzas });
94                                 elseif err == "auth" then
95                                         reply:tag("error", { type = "cancel" })
96                                                 :tag("not-allowed", { xmlns = xmlns_stanzas });
97                                 end
98                                 send(session, reply);
99                         else
100                                 local reply = st.reply(stanza);
101                                 reply:tag("bind", { xmlns = xmlns_bind})
102                                         :tag("jid"):text(session.full_jid);
103                                 send(session, reply);
104                         end
105                 end);
106                 
107 add_iq_handler("c2s", "urn:ietf:params:xml:ns:xmpp-session", 
108                 function (session, stanza)
109                         log("debug", "Client tried to bind to a resource");
110                         send(session, st.reply(stanza));
111                 end);