Merge with tip.
[prosody.git] / plugins / mod_tls.lua
1 -- Prosody IM
2 -- Copyright (C) 2008-2009 Matthew Wild
3 -- Copyright (C) 2008-2009 Waqas Hussain
4 -- 
5 -- This project is MIT/X11 licensed. Please see the
6 -- COPYING file in the source package for more information.
7 --
8
9 local st = require "util.stanza";
10
11 local xmlns_stream = 'http://etherx.jabber.org/streams';
12 local xmlns_starttls = 'urn:ietf:params:xml:ns:xmpp-tls';
13
14 local secure_auth_only = module:get_option("c2s_require_encryption") or module:get_option("require_encryption");
15 local secure_s2s_only = module:get_option("s2s_require_encryption");
16
17 module:add_handler("c2s_unauthed", "starttls", xmlns_starttls,
18                 function (session, stanza)
19                         if session.conn.starttls then
20                                 session.send(st.stanza("proceed", { xmlns = xmlns_starttls }));
21                                 session:reset_stream();
22                                 if session.host and hosts[session.host].ssl_ctx_in then
23                                         session.conn:set_sslctx(hosts[session.host].ssl_ctx_in);
24                                 end
25                                 session.conn:starttls();
26                                 session.log("info", "TLS negotiation started...");
27                                 session.secure = false;
28                         else
29                                 -- FIXME: What reply?
30                                 session.log("warn", "Attempt to start TLS, but TLS is not available on this connection");
31                         end
32                 end);
33                 
34 module:add_handler("s2sin_unauthed", "starttls", xmlns_starttls,
35                 function (session, stanza)
36                         if session.conn.starttls then
37                                 session.sends2s(st.stanza("proceed", { xmlns = xmlns_starttls }));
38                                 session:reset_stream();
39                                 if session.to_host and hosts[session.to_host].ssl_ctx_in then
40                                         session.conn:set_sslctx(hosts[session.to_host].ssl_ctx_in);
41                                 end
42                                 session.conn:starttls();
43                                 session.log("info", "TLS negotiation started for incoming s2s...");
44                                 session.secure = false;
45                         else
46                                 -- FIXME: What reply?
47                                 session.log("warn", "Attempt to start TLS, but TLS is not available on this s2s connection");
48                         end
49                 end);
50
51
52 local starttls_attr = { xmlns = xmlns_starttls };
53 module:add_event_hook("stream-features", 
54                 function (session, features)
55                         if session.conn.starttls then
56                                 features:tag("starttls", starttls_attr);
57                                 if secure_auth_only then
58                                         features:tag("required"):up():up();
59                                 else
60                                         features:up();
61                                 end
62                         end
63                 end);
64
65 module:hook("s2s-stream-features", 
66                 function (data)
67                         local session, features = data.session, data.features;
68                         if session.to_host and session.conn.starttls then
69                                 features:tag("starttls", starttls_attr):up();
70                                 if secure_s2s_only then
71                                         features:tag("required"):up():up();
72                                 else
73                                         features:up();
74                                 end
75                         end
76                 end);
77
78 -- For s2sout connections, start TLS if we can
79 module:hook_stanza(xmlns_stream, "features",
80                 function (session, stanza)
81                         module:log("debug", "Received features element");
82                         if session.conn.starttls and stanza:child_with_ns(xmlns_starttls) then
83                                 module:log("%s is offering TLS, taking up the offer...", session.to_host);
84                                 session.sends2s("<starttls xmlns='"..xmlns_starttls.."'/>");
85                                 return true;
86                         end
87                 end, 500);
88
89 module:hook_stanza(xmlns_starttls, "proceed",
90                 function (session, stanza)
91                         module:log("debug", "Proceeding with TLS on s2sout...");
92                         local format, to_host, from_host = string.format, session.to_host, session.from_host;
93                         session:reset_stream();
94                         session.conn:starttls(true);
95                         session.secure = false;
96                         return true;
97                 end);