2 -- Copyright (C) 2008-2010 Matthew Wild
3 -- Copyright (C) 2008-2010 Waqas Hussain
5 -- This project is MIT/X11 licensed. Please see the
6 -- COPYING file in the source package for more information.
11 local st
= require
"util.stanza";
12 local t_concat
= table.concat
;
14 local secure_auth_only
= module
:get_option("c2s_require_encryption",
15 module
:get_option("require_encryption"))
16 or not(module
:get_option("allow_unencrypted_plain_auth"));
18 local sessionmanager
= require
"core.sessionmanager";
19 local usermanager
= require
"core.usermanager";
20 local nodeprep
= require
"util.encodings".stringprep
.nodeprep
;
21 local resourceprep
= require
"util.encodings".stringprep
.resourceprep
;
23 module
:add_feature("jabber:iq:auth");
24 module
:hook("stream-features", function(event
)
25 local origin
, features
= event
.origin
, event
.features
;
26 if secure_auth_only
and not origin
.secure
then
27 -- Sorry, not offering to insecure streams!
29 elseif not origin
.username
then
30 features
:tag("auth", {xmlns
='http://jabber.org/features/iq-auth'}):up();
34 module
:hook("stanza/iq/jabber:iq:auth:query", function(event
)
35 local session
, stanza
= event
.origin
, event
.stanza
;
37 if session
.type ~= "c2s_unauthed" then
38 (session
.sends2s
or session
.send
)(st
.error_reply(stanza
, "cancel", "service-unavailable",
39 "Legacy authentication is only allowed for unauthenticated client connections."));
43 if secure_auth_only
and not session
.secure
then
44 session
.send(st
.error_reply(stanza
, "modify", "not-acceptable", "Encryption (SSL or TLS) is required to connect to this server"));
48 local query
= stanza
.tags
[1];
49 local username
= query
:get_child("username");
50 local password
= query
:get_child("password");
51 local resource
= query
:get_child("resource");
52 if not (username
and password
and resource
) then
53 local reply
= st
.reply(stanza
);
54 session
.send(reply
:query("jabber:iq:auth")
57 :tag("resource"):up());
59 username
, password
, resource
= t_concat(username
), t_concat(password
), t_concat(resource
);
60 username
= nodeprep(username
);
61 resource
= resourceprep(resource
)
62 if not (username
and resource
) then
63 session
.send(st
.error_reply(stanza
, "modify", "bad-request"));
66 if usermanager
.test_password(username
, session
.host
, password
) then
67 -- Authentication successful!
68 local success
, err
= sessionmanager
.make_authenticated(session
, username
);
70 local err_type
, err_msg
;
71 success
, err_type
, err
, err_msg
= sessionmanager
.bind_resource(session
, resource
);
73 session
.send(st
.error_reply(stanza
, err_type
, err
, err_msg
));
74 session
.username
, session
.type = nil, "c2s_unauthed"; -- FIXME should this be placed in sessionmanager?
76 elseif resource
~= session
.resource
then -- server changed resource, not supported by legacy auth
77 session
.send(st
.error_reply(stanza
, "cancel", "conflict", "The requested resource could not be assigned to this session."));
78 session
:close(); -- FIXME undo resource bind and auth instead of closing the session?
82 session
.send(st
.reply(stanza
));
84 session
.send(st
.error_reply(stanza
, "auth", "not-authorized"));