mod_tls: Add s2s_allow_encryption option which, when set to false, disabled TLS for s2s
[prosody.git] / plugins / mod_tls.lua
1 -- Prosody IM
2 -- Copyright (C) 2008-2010 Matthew Wild
3 -- Copyright (C) 2008-2010 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 local host = hosts[module.host];
18
19 local starttls_attr = { xmlns = xmlns_starttls };
20
21 --- Client-to-server TLS handling
22 module:add_handler("c2s_unauthed", "starttls", xmlns_starttls,
23                 function (session, stanza)
24                         if session.conn.starttls and host.ssl_ctx_in then
25                                 session.send(st.stanza("proceed", starttls_attr));
26                                 session:reset_stream();
27                                 if session.host and hosts[session.host].ssl_ctx_in then
28                                         session.conn.set_sslctx(hosts[session.host].ssl_ctx_in);
29                                 end
30                                 session.conn.starttls();
31                                 session.log("info", "TLS negotiation started...");
32                                 session.secure = false;
33                         else
34                                 session.log("warn", "Attempt to start TLS, but TLS is not available on this connection");
35                                 (session.sends2s or session.send)(st.stanza("failure", starttls_attr));
36                                 session:close();
37                         end
38                 end);
39
40 module:add_event_hook("stream-features", 
41                 function (session, features)
42                         if session.conn.starttls then
43                                 features:tag("starttls", starttls_attr);
44                                 if secure_auth_only then
45                                         features:tag("required"):up():up();
46                                 else
47                                         features:up();
48                                 end
49                         end
50                 end);
51 ---
52
53 -- Stop here if the user doesn't want to allow s2s encryption
54 if module:get_option("s2s_allow_encryption") == false then
55         return;
56 end
57
58 --- Server-to-server TLS handling
59 module:add_handler("s2sin_unauthed", "starttls", xmlns_starttls,
60                 function (session, stanza)
61                         if session.conn.starttls and host.ssl_ctx_in then
62                                 session.sends2s(st.stanza("proceed", starttls_attr));
63                                 session:reset_stream();
64                                 if session.to_host and hosts[session.to_host].ssl_ctx_in then
65                                         session.conn.set_sslctx(hosts[session.to_host].ssl_ctx_in);
66                                 end
67                                 session.conn.starttls();
68                                 session.log("info", "TLS negotiation started for incoming s2s...");
69                                 session.secure = false;
70                         else
71                                 session.log("warn", "Attempt to start TLS, but TLS is not available on this s2s connection");
72                                 (session.sends2s or session.send)(st.stanza("failure", starttls_attr));
73                                 session:close();
74                         end
75                 end);
76
77
78 module:hook("s2s-stream-features", 
79                 function (data)
80                         local session, features = data.session, data.features;
81                         if session.to_host and session.conn.starttls then
82                                 features:tag("starttls", starttls_attr);
83                                 if secure_s2s_only then
84                                         features:tag("required"):up():up();
85                                 else
86                                         features:up();
87                                 end
88                         end
89                 end);
90
91 -- For s2sout connections, start TLS if we can
92 module:hook_stanza(xmlns_stream, "features",
93                 function (session, stanza)
94                         module:log("debug", "Received features element");
95                         if session.conn.starttls and stanza:child_with_ns(xmlns_starttls) then
96                                 module:log("%s is offering TLS, taking up the offer...", session.to_host);
97                                 session.sends2s("<starttls xmlns='"..xmlns_starttls.."'/>");
98                                 return true;
99                         end
100                 end, 500);
101
102 module:hook_stanza(xmlns_starttls, "proceed",
103                 function (session, stanza)
104                         module:log("debug", "Proceeding with TLS on s2sout...");
105                         local format, to_host, from_host = string.format, session.to_host, session.from_host;
106                         local ssl_ctx = session.from_host and hosts[session.from_host].ssl_ctx or global_ssl_ctx;
107                         session.conn.set_sslctx(ssl_ctx);
108                         session:reset_stream();
109                         session.conn.starttls(true);
110                         session.secure = false;
111                         return true;
112                 end);